home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / pckermit.arc / PCKERMIT.ASM < prev    next >
Encoding:
Assembly Source File  |  1980-01-01  |  129.9 KB  |  3,676 lines

  1.      .XLIST
  2. ; KERMIT - KL10 Error-free Reciprocal Micro Interconnect over TTY-lines
  3. ;       Program Version 1.0, Kermit Protocol Version 1
  4. ;       February 1, 1983
  5. ;       Based on the KERMIT Protocol.
  6. ;       Copyright (C) 1982,1983 Trustees of Columbia University
  7. ;
  8. ;       Daphne Tzoar
  9. ;       Columbia University Computer Center
  10. ;       612 W. 115th St.
  11. ;       New York City, NY  10025
  12. ;  Special thanks to Frank da Cruz, Bill Catchings, Steve Jensen,
  13. ;  Vace Kundakci, and Bernie Eiben for their help and contributions.
  14.  
  15.  
  16. ;  This file is the global data area for all the Kermit modules.
  17.  
  18.  
  19. IBMPC   EQU     1               ; For IBM PC conditional assembly.
  20. STEVE   EQU     0               ; For Steve's homebrew assembly.
  21.  
  22. BELL    EQU     07Q
  23. TAB     EQU     11Q
  24. LF      EQU     12Q
  25. FF      EQU     14Q
  26. CR      EQU     15Q
  27. XON     EQU     21Q
  28. XOFF    EQU     23Q
  29. ESC     EQU     33Q
  30. DEL     EQU     177Q
  31. BS      EQU     08H
  32.  
  33. BIOS    EQU     10H
  34. DOS     EQU     21H
  35. COMM    EQU     14H
  36. KEYB    EQU     16H
  37.  
  38. CONIN   EQU     01H
  39. CONOUT  EQU     02H
  40. RDRIN   EQU     03H
  41. PUNOUT  EQU     04H
  42. LSTOUT  EQU     05H
  43. DCONIO  EQU     06H
  44. GTIOB   EQU     07H
  45. PRSTR   EQU     09H
  46. CONSTAT EQU     0BH
  47. OPENF   EQU     0FH
  48. CLOSF   EQU     10H
  49. SFIRST  EQU     11H
  50. SNEXT   EQU     12H
  51. DELF    EQU     13H
  52. READF   EQU     14H             ; Read from the file.
  53. WRITEF  EQU     15H
  54. MAKEF   EQU     16H
  55. CFLSZ   EQU     23H
  56.  
  57. DEFESC  EQU     ']'-100Q        ; The default escape character.
  58.  
  59. MAXPKT  EQU     '~'-' '+2Q      ; Maximum size of a packet.
  60. MAXTRY  EQU     05Q             ; Default number of retries on a packet.
  61. IMXTRY  EQU     20Q             ; Default number of retries send initiate.
  62. DRPSIZ  EQU     5EH             ; Default receive packet size.
  63. DSPSIZ  EQU     20H             ; Default send packet size.
  64. DSTIME  EQU     08H             ; Default send time out interval.
  65. DRTIME  EQU     05H             ; Default receive time out interval.
  66. DSPAD   EQU     00H             ; Default send padding.
  67. DRPAD   EQU     00H             ; Default receive padding.
  68. DSPADC  EQU     00H             ; Default send padding char.
  69. DRPADC  EQU     00H             ; Default receive padding char.
  70. DSEOL   EQU     CR              ; Default send EOL char.
  71. DREOL   EQU     CR              ; Default receive EOL char.
  72. DSQUOT  EQU     '#'             ; Default send quote char.
  73. DRQUOT  EQU     '#'             ; Default receive quote char.
  74.  
  75. SOH     EQU     01H             ; Start of header char.
  76.  
  77. BUFSIZ  EQU     80H             ; Size of DMA.
  78. MAXFIL  EQU     50H             ; Maximum number of files allowed.
  79.  
  80. DIASW   EQU     01H             ; Default is diagnostics on.
  81.  
  82. CMKEY   EQU     01H             ; Parse a keyword.
  83. CMIFI   EQU     02H             ; Parse an input file spec (can be wild).
  84. CMOFI   EQU     03H             ; Parse an output file spec.
  85. CMCFM   EQU     04H             ; Parse a confirm.
  86.  
  87. TIMER   EQU     40H             ; Use to issue short beep.
  88. PORT_B  EQU     61H             ; Port B address.
  89. B0300   EQU    180H             ; Variables for 300 baud, 1200, etc.
  90. B1200   EQU     60H
  91. B1800   EQU     40H
  92. B2400   EQU     30H
  93. B4800   EQU     18H
  94. B9600   EQU     0CH
  95.  
  96. STACK   SEGMENT PARA STACK 'STACK'
  97.         DW      100 DUP(0)      ; Initialize stack to all zeros.
  98. STK     EQU     THIS WORD
  99. STACK   ENDS
  100.  
  101. DATAS   SEGMENT PARA PUBLIC 'DATAS'
  102.  
  103.         ; Pure storage.
  104.  
  105. versio  db      'CUCCA IBM-PC Kermit-86 - ver 1.0',cr,lf,
  106.         db      'Field Test Version',cr,lf,'$'
  107. kerm    db      'Kermit-86>$'
  108. spmes   db      'Spack:  $'
  109. rpmes   db      'Rpack:  $'
  110. hibit   db      'Warning - Non Ascii char$'
  111. tmp     db      ?
  112. foo     db      '$'
  113. crlf    db      cr,lf,'$'
  114. tmsg1   db      cr,lf,'[Connecting to host,' 
  115.         db      'type Ctrl-]-C to return to PC]',cr,lf,'$'
  116. tmsg2   db      cr,lf,'[Back at micro]',cr,lf,'$'
  117. ermes1  db      cr,lf,'?Unregonized command$'
  118. ermes2  db      cr,lf,'?Illegal character$'
  119. ermes3  db      cr,lf,'?Not confirmed$'
  120. ermes4  db      'Unable to rename file$'
  121. ermes5  db      cr,lf,'?Disk full$'
  122. ermes7  db      '?Unable to receive initiate$'
  123. ermes8  db      '?Unable to receive file name$'
  124. ermes9  db      '?Unable to receive end of file$'
  125. erms10  db      '?Unable to receive data$'
  126. erms11  db      '?Disk full$'
  127. erms14  db      '?Unable to receive an acknowledgement from the host$'
  128. erms15  db      '?Unable to find file$'
  129. erms19  db      'Record length exceeds size of buffer$'
  130. dimsg1  db      '%Bad checksum$'
  131. infms0  db      'Waiting .....$'
  132. infms1  db      'Receiving ...$'
  133. infms2  db      'Sending .....$'
  134. infms3  db      'Completed    $'
  135. infms4  db      'Failed       $'
  136. infms5  db      'Renaming file to $'
  137.  
  138. cfrmes  db      ' Confirm with carriage return $'
  139. ; filhlp  db      ' Input file spec (possibly wild) $'
  140. filhlp  db      ' Input file spec $'
  141. ;spchar db      $,&,#,@,!,%,',(,),-,<,>,{,},_,\,^,~,|,`
  142. spchar  db      24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  143.         db      3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H
  144. escmes  db      cr,lf,'Type the new escape character:  $'
  145. eschlp  db      cr,lf,'Enter literal value (ex: Cntrl ])  $'
  146. tophlp  db      cr,lf,'CONNECT to host on selected port'
  147.         db      cr,lf,'EXIT to DOS'
  148.         db      cr,lf,'HELP by giving this message'
  149.         db      cr,lf,'RECEIVE file from host'
  150.         db      cr,lf,'SEND file to host'
  151.         db      cr,lf,'SET a parameter'
  152. ;        db      cr,lf,'SHOW the parameters'
  153.         db      cr,lf,'STATUS of Kermit$'
  154. sethlp  db      cr,lf,'BAUD rate'
  155.         db      cr,lf,'DEBUG'
  156.         db      cr,lf,'ESCAPE character change'
  157.         db      cr,lf,'FILE-WARNING'
  158.         db      cr,lf,'IBM'
  159.         db      cr,lf,'LOCAL-ECHO echoing (half-duplex)'
  160. ;        db      cr,lf,'RECEIVE parameter'
  161. ;        db      cr,lf,'SEND parameter'
  162.         db      cr,lf,'VT52-EMULATION$'
  163. stshlp  db      cr,lf,'PAD-CHAR'
  164.         db      cr,lf,'PADDING$'
  165. onhlp   db      cr,lf,'OFF      ON$'
  166. yeshlp  db      cr,lf,'NO       YES$'
  167. bdhlp   db      cr,lf,'300   1200   1800   2400   4800   9600$'
  168. inthlp  db      cr,lf,'?  This message'
  169.         db      cr,lf,'C  Close the connection'
  170.         db      cr,lf,'S  Status of the connection'
  171.         db      cr,lf,'Typing the escape character will send it to the host'
  172.         db      cr,lf,cr,lf,'Command>$'
  173. locst   db      cr,lf,'Local echo on$'
  174. remst   db      cr,lf,'Local echo off$'
  175. vtemst  db      cr,lf,'VT52 emulation on$'
  176. novtst  db      cr,lf,'VT52 emulation off$'
  177. ibmst   db      cr,lf,'IBM on$'
  178. noibm   db      cr,lf,'IBM off$'
  179. b03st   db      cr,lf,'Baud rate is 300$'
  180. b12st   db      cr,lf,'Baud rate is 1200$'
  181. b18st   db      cr,lf,'Baud rate is 1800$'
  182. b24st   db      cr,lf,'Baud rate is 2400$'
  183. b48st   db      cr,lf,'Baud rate is 4800$'
  184. b96st   db      cr,lf,'Baud rate is 9600$'
  185. debon   db      cr,lf,'Debug mode on$'
  186. deboff  db      cr,lf,'Debug mode off$' 
  187. flwon   db      cr,lf,'File Warning on$'
  188. flwoff  db      cr,lf,'File Warning off$'
  189.  
  190.  
  191. outlin  db      cr,lf,'                CUCCA IBM-PC Kermit-86 V1.0',
  192.         db      '  Field Test Version',cr,lf
  193.         db      cr,lf,'Number of packets        (hex)'
  194.         db      cr,lf,'Number of retries        (hex)'
  195.         db      cr,lf,'File name $'
  196. delstr  db      10O,' ',10O,10O,'$'     ; Delete string.
  197. clrspc  db      ' ',10O,'$'             ; Clear space.
  198. escspc  db      10O,' ',10O,'$'         ; Clear escape.
  199. clrlin  db      cr,'$'                  ; Clear line (just the cr part).
  200. prsp    db      ' $'                    ; Print a space.
  201. scrhi   dw      0434H                   ; Err when 8th bit is on.
  202. scrrpr  dw      0700H                   ; Prompt when Kermit ends.
  203. screrr  dw      0600H                   ; Place for error msgs. 
  204. scrfln  dw      050CH                   ; Place for file name.
  205. scrnrt  dw      0415H                   ; Place for number of retries.
  206. scrnp   dw      0315H                   ; Place for number of packets.
  207. scrfr   dw      0600H                   ; Rename file.
  208. scrst   dw      0334H                   ; Place for status.
  209. scrsp   dw      0800H                   ; Place for send packet.
  210. scrrp   dw      0A00H                   ; Place for receive packet.
  211. ttab    label   word                    ; Table for cursor movement.
  212. ta      dw      curup                   ; Cursor up.
  213. tb      dw      curdwn                  ; Cursor down.
  214. tc      dw      currt                   ; Cursor right.
  215. td      dw      curlft                  ; Cursor left.
  216. te      dw      curskp                  ; Clear display.
  217. tf      dw      curskp                  ; Enter graphics mode.
  218. tg      dw      curskp                  ; Exit graphics mode.
  219. th      dw      curhm                   ; Cursor home.
  220. ti      dw      curup                   ; Reverse line feed.
  221. tj      dw      curscr                  ; Clear to end of screen.
  222. tk      dw      curln                   ; Clear to end of line.
  223. tl      dw      inslin                  ; Insert line.
  224. tm      dw      dellin                  ; Delete line.  
  225.  
  226.         ; COMND tables
  227.  
  228. comtab  db      07H             ; seven entries.
  229.         db      07H,'CONNECT$'
  230.         dw      telnet
  231.         db      04H,'EXIT$'
  232.         dw      exit
  233.         db      04H,'HELP$'
  234.         dw      help
  235.         db      07H,'RECEIVE$'
  236.         dw      read
  237.         db      04H,'SEND$'
  238.         dw      send
  239.         db      03H,'SET$'
  240.         dw      setcom
  241.         db      06H,'STATUS$'
  242.         dw      status
  243.  
  244.  
  245. settab  db      07H             ; seven entries.
  246.         db      04H,'BAUD$'
  247.         dw      baudst
  248.         db      05H,'DEBUG$'
  249.         dw      debst
  250.         db      06H,'ESCAPE$'
  251.         dw      escape
  252.         db      0CH,'FILE-WARNING$'
  253.         dw      filwar
  254.         db      03H,'IBM$'
  255.         dw      ibmset
  256.         db      0AH,'LOCAL-ECHO$'
  257.         dw      lcal
  258.         db      0EH,'VT52-EMULATION$'
  259.         dw      vt52em
  260.  
  261. ontab   db      02H             ; Two entries.
  262.         db      02H,'ON$'
  263.         dw      01H
  264.         db      03H,'OFF$'
  265.         dw      00H
  266.  
  267. yestab  db      02H             ; Two entries.
  268.         db      02H,'NO$'
  269.         dw      00H
  270.         db      03H,'YES$'
  271.         dw      01H
  272.  
  273. bdtab   db      06H             ; Six entries.
  274.         db      04H,'1200$'
  275.         dw      B1200
  276.         db      04H,'1800$'
  277.         dw      B1800
  278.         db      04H,'2400$'
  279.         dw      B2400
  280.         db      03H,'300$'
  281.         dw      B0300
  282.         db      04H,'4800$'
  283.         dw      B4800
  284.         db      04H,'9600$'
  285.         dw      B9600
  286.  
  287. ; COMND storage
  288.  
  289. cmer00  db      cr,lf,'?Program error   Invalid COMND call$'
  290. cmer01  db      cr,lf,'?Ambiguous$'
  291. cmer02  db      cr,lf,'?Illegal input file spec$'
  292. cmer03  db      cr,lf,'?Unrecognized instruction$'
  293. cmin00  db      ' Confirm with carriage return$'
  294. cmcrlf  db      cr,lf,'$'
  295.  
  296. cmstat  db      ?               ; What is presently being parsed.
  297. cmaflg  db      ?               ; Non-zero when an action char has been found.
  298. cmccnt  db      ?               ; Non-zero if a significant char is found.
  299. cmsflg  db      ?               ; Non-zero when the last char was a space.
  300. cmostp  dw      ?               ; Old stack pointer for reparse.
  301. cmrprs  dw      ?               ; Address to go to on reparse.
  302. cmprmp  dw      ?               ; Address of prompt.
  303. cmptab  dw      ?               ; Address of present keyword table.
  304. cmhlp   dw      ?               ; Address of present help.
  305. cmdbuf  db      80H DUP(?)      ; Buffer for command parsing.
  306. cmfcb   dw      ?               ; Pointer to FCB.
  307. cmfcb2  dw      ?               ; Pointer to position in FCB.
  308. cmcptr  dw      ?               ; Pointer for next char input.
  309. cmdptr  dw      ?               ; Pointer into the command buffer.
  310. cmsiz   dw      ?               ; Size info of user input.
  311. cmkptr  dw      ?               ; Pointer to keyword.
  312. cmsptr  dw      ?               ; Place to save a pointer.
  313. cmchr   db      ?               ; Save char when checking ambiguity.
  314.  
  315. ; Program storage.
  316.  
  317. oldstk  dw      ?               ; Storage for system stack.
  318. oldsts  dw      ?               ; System stack segment.
  319. ssp     dw      0               ; Save SP in Telnet.
  320. bufhex  dw      80H
  321. filsiz  dd      0               ; Double word for filesize (in bytes.)
  322. eoflag  db      ?               ; EOF flag; non-zero on EOF.
  323. debug   db      0               ; Debugging mode (default off).
  324. hierr   db      0               ; Non-ascii char (non-zero if yes).
  325. filflg  db      ?               ; Non-zero when nothing in DMA buffer.
  326. ecoflg  db      0               ; Local echo flag (default off).
  327. escflg  db      0               ; Escape flag (start off).
  328. vtflg   db      1               ; VT52 emulation flag (default on).
  329. flwflg  db      0               ; File warning flag (default off).
  330. ibmflg  db      0               ; IBM flag (default off).
  331. extflg  db      0               ; Exit flag (default off).
  332. escchr  db      defesc          ; Storage for the escape character.
  333. incnt   dw      ?               ; Number of chars read in from port.
  334. chrcnt  dw      ?               ; Number of chars in the file buffer.
  335. filcnt  dw      ?               ; Number of chars left to fill.
  336. outpnt  dw      ?               ; Position in packet.
  337. bufpnt  dw      ?               ; Position in file buffer.
  338. fcbptr  dw      ?               ; Position in FCB.
  339. datptr  dw      ?               ; Position in packet data buffer.
  340. cbfptr  dw      ?               ; Position in character buffer.
  341. pktptr  dw      ?               ; Poistion in receive packet.
  342. siz     dw      ?               ; Size of data from gtchr.
  343. baud    dw      B4800           ; Use default of 4800.
  344. spsiz   db      dspsiz          ; Send packet size.
  345. rpsiz   db      drpsiz          ; Receive packet size.
  346. stime   db      dstime          ; Send time out.
  347. rtime   db      drtime          ; Receive time out.
  348. spad    db      dspad           ; Send padding.
  349. rpad    db      drpad           ; Receive padding.
  350. spadch  db      dspadc          ; Send padding char.
  351. rpadch  db      drpadc          ; Receive padding char.
  352. seol    db      dseol           ; Send EOL char.
  353. reol    db      dreol           ; Receive EOL char.
  354. squote  db      dsquot          ; Send quote char.
  355. rquote  db      drquot          ; Receive quote char.
  356. pktnum  dw      ?               ; Packet number.
  357. numpkt  dw      ?               ; Total number of packets sent.
  358. numrtr  dw      ?               ; Total number of retries.
  359. numtry  db      ?               ; Number of tries on this packet.
  360. oldtry  db      ?               ; Number of tries on previous packet.
  361. state   db      ?               ; Present state of the automaton.
  362. packet  db      ?,?,?,?         ; Packet (data is part of it).
  363. data    db      5AH DUP(?)      ; Data and checksum field of packet.
  364. recpkt  db      60H DUP(?)      ; Receive packet storage (use the following).
  365. filbuf  db      60H DUP(?)      ; Character buffer.
  366. fcb     db      25H DUP(?)      ; Use as our FCB.
  367. buff    db      80H DUP(?)      ; Use as our DAT.
  368. rdbuf   db      80H DUP(?)
  369. cnt     dw      0
  370. temp    dw      0
  371. temp1   dw      ?               ; Temporary storage.
  372. temp2   dw      ?
  373. temp3   dw      ?
  374. temp4   dw      ?
  375. argblk  dw      ?               ; For subroutine arguments.
  376. argbk1  dw      ?
  377. argbk2  dw      ?
  378. argbk3  dw      ?
  379. fcbnum  dw      ?               ; Number of FCB's left in the list.
  380.  
  381. DATAS   ENDS                    ; End data segment
  382.  
  383.  
  384. MAIN    SEGMENT PARA PUBLIC 'MAIN'
  385. START   PROC  FAR
  386.         ASSUME  CS:MAIN,DS:DATAS,SS:STACK,ES:NOTHING
  387.  
  388.         push ds                 ; Save system data area.
  389.         sub ax,ax               ; Get a zero.
  390.         push ax                 ; Put zero return addr on stack.
  391.  
  392.         call cmblnk             ; Clear the screen.
  393.         call locate
  394.  
  395.         mov ax,datas            ; Initialize DS.
  396.         mov ds,ax
  397.         sub ax,ax
  398.  
  399.         mov oldstk,sp           ; Save old stack pointer.
  400. ;        mov ax,ss
  401. ;        mov oldsts,ax
  402.  
  403.  
  404. ;        mov ax,stack            ; Initialize SS.
  405. ;        mov ss,ax
  406. ;        mov sp,offset ss:stk
  407. ;        sub ax,ax
  408.  
  409.         mov ah,prstr            ; Print the version header.
  410.         mov dx,offset versio
  411.         int dos
  412.  
  413.         mov ah,1AH              ; Set disk transfer address.
  414.         mov dx,offset buff
  415.         int dos
  416.  
  417.         mov dx,03FBH            ; LCR -- Initialize baud rate.
  418.         in al,dx
  419.         mov bl,al
  420.         or ax,80H
  421.         out dx,al
  422.         mov dx,03F8H
  423.         mov ax,baud
  424.         out dx,al
  425.         inc dx
  426.         mov al,ah
  427.         out dx,al
  428.         mov dx,03FBH
  429.         mov al,bl
  430.         out dx,al
  431.  
  432.  
  433.  
  434. ; This is the main KERMIT loop.  It prompts for and gets the users commands.
  435.  
  436. kermit: mov dx,offset kerm
  437.         call prompt             ; Prompt the user.
  438.         mov dx,offset comtab
  439.         mov bx,offset tophlp
  440.         mov ah,cmkey
  441.         call comnd
  442.          jmp kermt2
  443.         call bx                 ; Call the routine returned.
  444.          jmp kermt3
  445.         cmp extflg,0            ;  Check if the exit flag is set.
  446.         jne finish              ;  If so jump to FINISH.
  447.         jmp kermit              ; Do it again.
  448.  
  449. kermt2: mov ah,prstr
  450.         mov dx,offset ermes1    ;  Give an error.
  451.         int dos
  452.         jmp kermit
  453.  
  454. kermt3: mov ah,prstr
  455.         mov dx,offset ermes3    ;  Give an error.
  456.         int dos
  457.         jmp kermit
  458.  
  459. finish: 
  460. ;        mov ax,oldsts           ; Restore the old stack.
  461. ;        mov ss,ax
  462.         mov sp,oldstk
  463.         ret
  464.  
  465. START   ENDP
  466.  
  467.  
  468. ; These are some utility routines.
  469.  
  470. ;       Abort
  471.  
  472. ABORT   PROC    NEAR
  473.         mov state,'A'           ; Otherwise abort.
  474.         ret
  475. ABORT   ENDP
  476.  
  477. ;       NAK
  478.  
  479. NAK     PROC    NEAR
  480.         mov ax,pktnum           ; Get the packet number we're waiting for.
  481.         mov argblk,ax
  482.         mov argbk1,0
  483.         mov ah,'N'              ; NAK that packet.
  484.         call spack
  485.         ret                     ; Go around again.
  486. NAK     ENDP
  487.  
  488. ; Position cursor for an error message.
  489.  
  490. ERPOS   PROC    NEAR
  491.         mov ah,2
  492.         mov bh,0
  493.         mov dx,screrr
  494.         int bios
  495.         ret
  496. ERPOS   ENDP
  497.  
  498. ; Position cursor for number of retries message.
  499.  
  500. RTPOS   PROC    NEAR
  501.         mov ah,2
  502.         mov bh,0
  503.         mov dx,scrnrt
  504.         int bios
  505.         ret
  506. RTPOS   ENDP
  507.  
  508. ; Print err message that found a non-standard-Ascii char in the file.
  509.  
  510. BITERR  PROC    NEAR
  511.         push bx
  512.         mov ah,2
  513.         mov bh,0
  514.         mov dx,scrhi
  515.         int bios
  516.         mov ah,prstr
  517.         mov dx,offset hibit
  518.         int dos
  519.         pop bx
  520.         ret
  521. BITERR  ENDP            
  522.  
  523. ;       This routine sets up the data for init packet (either the
  524. ;       Send_init or ACK packet).
  525.  
  526. RPAR    PROC    NEAR
  527.         mov ah,rpsiz            ; Get the receive packet size.
  528.         add ah,' '              ; Add a space to make it printable.
  529.         mov [bx],ah             ; Put it in the packet.
  530.         mov ah,rtime            ; Get the receive packet time out.
  531.         add ah,' '              ; Add a space.
  532.         mov 1[bx],ah            ; Put it in the packet.
  533.         mov ah,rpad             ; Get the number of padding chars.
  534.         add ah,' '
  535.         mov 2[bx],ah            ; Put it in the packet.
  536.         mov ah,rpadch           ; Get the padding char.
  537.         add ah,100O             ; Uncontrol it.
  538.         and ah,7FH
  539.         mov 3[bx],ah            ; Put it in the packet.
  540.         mov ah,reol             ; Get the EOL char.
  541.         add ah,' '
  542.         mov 4[bx],ah            ; Put it in the packet.
  543.         mov ah,rquote           ; Get the quote char.
  544.         mov 5[bx],ah            ; Put it in the packet.
  545.         mov ah,06H              ; Six pieces of data.
  546.         ret
  547. RPAR    ENDP
  548.  
  549. ;       This routine reads in all the send_init packet information.
  550.  
  551. SPAR    PROC    NEAR
  552.         mov temp4,ax            ; Save the number of arguments.
  553.         mov ah,[bx]             ; Get the max packet size.
  554.         sub ah,' '              ; Subtract a space.
  555.         mov spsiz,ah            ; Save it.
  556.         mov ax,temp4
  557.         cmp al,3                ; Fewer than three pieces?
  558.         jge spar1
  559.         ret                     ; If so we are done.
  560. spar1:  mov ah,2[bx]            ; Get the number of padding chars.
  561.         sub ah,' '
  562.         mov spad,ah
  563.         mov ax,temp4
  564.         cmp al,4                ; Fewer than four pieces?
  565.         jge spar2
  566.         ret                     ; If so we are done.
  567. spar2:  mov ah,3[bx]            ; Get the padding char.
  568.         add ah,100O             ; Re-controlify it.
  569.         and ah,7FH
  570.         mov spadch,ah
  571.         mov ax,temp4
  572.         cmp al,5                ; Fewer than five pieces?
  573.         jge spar3
  574.         ret                     ; If so we are done.
  575. spar3:  mov ah,4[bx]            ; Get the EOL char.
  576.         sub ah,' '
  577.         mov seol,ah
  578.         mov ax,temp4
  579.         cmp al,6                ; Fewer than six pieces?
  580.         jge spar4
  581.         ret                     ; If so we are done.
  582. spar4:  mov ah,5[bx]            ; Get the quote char.
  583.         mov squote,ah
  584.         ret
  585. SPAR    ENDP
  586.  
  587.  
  588. ;       Initialize buffers and clear line.
  589.  
  590. INIT    PROC    NEAR
  591.         call cmblnk
  592.         call locate
  593.         mov ah,prstr            ; Put statistics headers on the screen.
  594.         mov dx,offset outlin
  595.         int dos
  596.         call init1
  597.         ret
  598. INIT    ENDP
  599.  
  600. INIT1   PROC    NEAR
  601.         mov chrcnt,bufsiz       ;* Number of chars left.
  602.         mov bufpnt,offset buff         ; Addr for beginning.
  603.         ret
  604. INIT1   ENDP
  605.  
  606. ;  Clear out the old filename on the screen. 
  607.  
  608. CLRFLN  PROC    NEAR
  609.         mov ah,2
  610.         mov bh,0
  611.         mov dx,scrfln
  612.         int bios
  613.         mov ax,0920H                    ; Clear out the old filename.
  614.         mov bx,7
  615.         mov cx,12
  616.         int bios
  617.         ret
  618. CLRFLN  ENDP
  619.  
  620. ;       RECEIVE command
  621.  
  622. READ    PROC    NEAR
  623.         mov ah,cmcfm
  624.         call comnd              ; Get a confirm.
  625.          jmp r
  626.         call init               ; Clear the line and initialize the buffers.
  627.         mov numpkt,0            ; Set the number of packets to zero.
  628.         mov numrtr,0            ; Set the number of retries to zero.
  629.         mov pktnum,0            ; Set the packet number to zero.
  630.         mov numtry,0            ; Set the number of tries to zero.
  631.         call rtpos              ; Position cursor.
  632.         mov ax,numrtr
  633.         call nout               ; Write the number of retries.
  634.         mov state,'R'           ; Set the state to receive initiate.
  635. read2:  mov ah,2                ; Position cursor.
  636.         mov dx,scrst
  637.         mov bh,0
  638.         int bios
  639.         mov ah,prstr            ; Be informative.
  640.         mov dx,offset infms1
  641.         int dos
  642.         mov ah,2
  643.         mov dx,scrnp
  644.         mov bh,0
  645.         int bios
  646.         mov ax,numpkt
  647.         call nout               ; Write the number of packets.
  648.         mov ah,state            ; Get the state.
  649.         cmp ah,'D'              ; Are we in the data send state?
  650.         jne read3
  651.         call rdata
  652.         jmp read2
  653. read3:  cmp ah,'F'              ; Are we in the file receive state?
  654.         jne read4
  655.         call rfile              ; Call receive file.
  656.         jmp read2
  657. read4:  cmp ah,'R'              ; Are we in the receive initiate state?
  658.         jne read5
  659.         call rinit
  660.         jmp read2
  661. read5:  cmp ah,'C'              ; Are we in the receive complete state?
  662.         jne read6
  663.         mov ah,2                ; Position cursor.
  664.         mov dx,scrst
  665.         mov bh,0
  666.         int bios
  667.         mov dx,offset infms3    ; Plus a little cuteness.
  668.         mov ah,prstr
  669.         int dos
  670.         mov ah,2
  671.         mov dx,scrrpr           ; Put prompt here.
  672.         mov bh,0
  673.         int bios
  674.         jmp rskp
  675. read6:  mov ah,2                ; Position cursor.
  676.         mov dx,scrst
  677.         mov bh,0
  678.         int bios
  679.         mov dx,offset infms4    ; Plus a little cuteness.
  680.         mov ah,prstr
  681.         int dos
  682.         mov ah,2
  683.         mov dx,scrrpr
  684.         mov bh,0
  685.         int bios
  686.         jmp rskp
  687. READ    ENDP
  688.  
  689.  
  690. ;       Receive routines
  691.  
  692. ;       Receive init
  693.  
  694. RINIT   PROC    NEAR
  695.         mov ah,numtry           ; Get the number of tries.
  696.         cmp ah,imxtry           ; Have we reached the maximum number of tries?
  697.         jl rinit2
  698.         call erpos              ; Position cursor.
  699.         mov dx,offset ermes7
  700.         mov ah,prstr
  701.         int dos                 ; Print an error message.
  702.         jmp abort               ; Change the state to abort.
  703. rinit2: inc ah                  ; Increment it.
  704.         mov numtry,ah           ; Save the updated number of tries.
  705.         call rpack              ; Get a packet.
  706.          jmp nak                ;  Trashed packet: nak, retry.
  707.         cmp ah,'S'              ; Is it a send initiate packet?
  708.         jne rinit3              ; If not see if its an error.
  709.         mov ah,numtry           ; Get the number of tries.
  710.         mov oldtry,ah           ; Save it.
  711.         mov numtry,0            ; Reset the number of tries.
  712.         mov ax,argblk           ; Returned packet number.  (Synchronize them.)
  713.         inc ax                  ; Increment it.
  714.         and ax,3FH              ; Turn off the two high order bits.
  715.         mov pktnum,ax           ; Save modulo 64 of the number.
  716.         mov bx,numpkt
  717.         inc bx                  ; Increment the number of packets.
  718.         mov numpkt,bx
  719.         mov ax,argbk1           ; Get the number of arguments received.
  720.         mov bx,offset data      ; Get a pointer to the data.
  721.         call spar               ; Get the data into the proper variables.
  722.         mov bx,offset data      ; Get a pointer to our data block.
  723.         call rpar               ; Set up the receive parameters.
  724.         xchg ah,al
  725.         mov ah,0
  726.         mov argbk1,ax           ; Store the returned number of arguments.
  727.         mov ah,'Y'              ; Acknowledge packet.
  728.         call spack              ; Send the packet.
  729.         mov ah,'F'              ; Set the state to file send.
  730.         mov state,ah
  731.         ret
  732. rinit3: cmp ah,'E'              ; Is it an error packet?
  733.         jne rinit4
  734.         call error
  735. rinit4: jmp abort
  736. RINIT   ENDP
  737.  
  738.  
  739. ;       Receive file
  740.  
  741. RFILE   PROC    NEAR
  742.         cmp numtry,maxtry       ; Have we reached the maximum number of tries?
  743.         jl rfile1
  744.         call erpos              ; Position cursor.
  745.         mov dx,offset ermes8
  746.         mov ah,prstr
  747.         int dos                 ; Print an error message.
  748.         jmp abort               ; Change the state to abort.
  749. rfile1: inc numtry              ; Save the updated number of tries.
  750.         call rpack              ; Get a packet.
  751.          jmp nak                ;  Trashed packet: nak, retry.
  752.         cmp ah,'S'              ; Is it a send initiate packet?
  753.         jne rfile2              ;  No, try next type.
  754.         cmp oldtry,imxtry       ; Have we reached the maximum number of tries?
  755.         jl rfil12               ; If not proceed.
  756.         call erpos              ; Position cursor.
  757.         mov dx,offset ermes7
  758.         mov ah,prstr
  759.         int dos                 ; Print an error message.
  760.         jmp abort               ; Change the state to abort.
  761. rfil12: inc oldtry              ; Save the updated number of tries.
  762.         mov ax,pktnum           ; Get the present packet number.
  763.         dec ax                  ; Decrement.
  764.         cmp ax,argblk           ; Is the packet's number one less than now?
  765.         je rfil13
  766.         jmp nak                 ; No, NAK and try again.
  767. rfil13: call rtpos              ; Position cursor.
  768.         inc numrtr              ; Increment the number of retries.
  769.         mov ax,numrtr
  770.         call nout               ; Write the number of retries.
  771.         mov numtry,0            ; Reset the number of tries.
  772.         mov bx,offset data      ; Get a pointer to our data block.
  773.         call rpar               ; Set up the parameter information.
  774.         xchg ah,al
  775.         mov ah,0
  776.         mov argbk1,ax           ; Save the number of arguments.
  777.         mov ah,'Y'              ; Acknowledge packet.
  778.         call spack              ; Send the packet.
  779.         ret
  780. rfile2: cmp ah,'Z'              ; Is it an EOF packet?
  781.         jne rfile3              ;  No, try next type.
  782.         cmp oldtry,maxtry       ; Have we reached the maximum number of tries?
  783.         jl rfil21               ; If not proceed.
  784.         call erpos              ; Position cursor.
  785.         mov dx,offset ermes9
  786.         mov ah,prstr
  787.         int dos                 ; Print an error message.
  788.         jmp abort               ; Change the state to abort.
  789. rfil21: inc oldtry              ; Increment it.
  790.         mov ax,pktnum           ; Get the present packet number.
  791.         dec ax                  ; Decrement.
  792.         cmp ax,argblk           ; Is the packet's number one less than now?
  793.         je rfil24
  794.         jmp nak                 ; No, NAK and try again.
  795. rfil24: call rtpos              ; Position cursor.
  796.         inc numrtr              ; Increment the number of retries
  797.         mov ax,numrtr
  798.         call nout               ; Write the number of retries.
  799.         mov numtry,0
  800.         mov argbk1,0            ; No data.  (The packet number is in argblk.)
  801.         mov ah,'Y'              ; Acknowledge packet.
  802.         call spack              ; Send the packet.
  803.         ret
  804. rfile3: cmp ah,'F'              ; Start of file?
  805.         jne rfile4
  806.         mov ax,argblk           ; Get the packet number.
  807.         cmp ax,pktnum           ; Is it the right packet number?
  808.         je rfil32
  809.         jmp nak                 ; No, NAK it and try again.
  810. rfil32: inc ax                  ; Increment the packet number.
  811.         and ax,3FH              ; Turn off the two high order bits.
  812.         mov pktnum,ax           ; Save modulo 64 of the number.
  813.         inc numpkt              ; Increment the number of packets.
  814.         call gofil              ; Get a file to write to.
  815.          jmp abort
  816.         call init1              ; Initialize all the buffers.
  817.         mov ah,numtry           ; Get the number of tries.
  818.         mov oldtry,ah           ; Save it.
  819.         mov numtry,0            ; Reset the number of tries.
  820.         mov argbk1,0            ; No data.  (The packet number is in argblk.)
  821.         mov ah,'Y'              ; Acknowledge packet.
  822.         call spack              ; Send the packet.
  823.         mov state,'D'           ; Set the state to data receive.
  824.         ret
  825. rfile4: cmp ah,'B'              ; End of transmission.
  826.         jne rfile5
  827.         mov ax,pktnum
  828.         cmp ax,argblk           ; Do we match?
  829.         je rfil41
  830.         jmp nak                 ; No, NAK it and try again.
  831. rfil41: mov argbk1,0            ; No data.  (Packet number already in argblk).
  832.         mov ah,'Y'              ; Acknowledge packet.
  833.         call spack              ; Send the packet.
  834.         mov state,'C'           ; Set the state to complete.
  835.         ret
  836. rfile5: cmp ah,'E'              ; Is it an error packet.
  837.         jne rfile6
  838.         call error
  839. rfile6: jmp abort
  840. RFILE   ENDP
  841.  
  842.  
  843. ;       Receive data
  844.  
  845. RDATA   PROC    NEAR
  846.         cmp numtry,maxtry       ; Get the number of tries.
  847.         jl rdata1
  848.         call erpos              ; Position cursor.
  849.         mov dx,offset erms10
  850.         mov ah,prstr
  851.         int dos                 ; Print an error message.
  852.         jmp abort               ; Change the state to abort.
  853. rdata1: inc numtry              ; Save the updated number of tries.
  854.         call rpack              ; Get a packet.
  855.          jmp nak                ;  Trashed packet: nak, retry.
  856.         cmp ah,'D'              ; Is it a data packet?
  857.         jne rdata2              ;  No, try next type.
  858. rdat11: mov ax,pktnum           ; Get the present packet number.
  859.         cmp ax,argblk           ; Is the packet's number correct?
  860.         jz rdat14
  861.         cmp oldtry,maxtry       ; Have we reached the maximum number of tries?
  862.         jl rdat12               ; If not proceed.
  863.         call erpos              ; Position cursor.
  864.         mov dx,offset erms10
  865.         mov ah,prstr
  866.         int dos                 ; Print an error message.
  867.         jmp abort               ; Change the state to abort.
  868. rdat12: inc oldtry              ; Save the updated number of tries.
  869.         dec pktnum              ; Decrement present packet number.
  870.         mov ax,pktnum
  871.         cmp ax,argblk           ; Is the packet's number one less than now?
  872.         je rdat13
  873.         jmp nak                 ; No, NAK it and try again.
  874. rdat13: call rtpos              ; Position cursor.
  875.         inc numrtr              ; Increment the number of retries
  876.         mov ax,numrtr
  877.         call nout               ; Write the number of retries.
  878.         mov numtry,0            ; Reset number of tries.
  879.         mov argbk1,0            ; No data.  (The packet number is in argblk.)
  880.         mov ah,'Y'              ; Acknowledge packet.
  881.         call spack              ; Send the packet.
  882.         ret
  883. rdat14: inc ax                  ; Increment the packet number.
  884.         and ax,3FH              ; Turn off the two high order bits.
  885.         mov pktnum,ax           ; Save modulo 64 of the number.
  886.         inc numpkt              ; Increment the number of packets.
  887.         mov ah,numtry           ; Get the number of tries.
  888.         mov oldtry,ah           ; Save it.
  889.         mov ax,argbk1           ; Get the length of the data.
  890.         call ptchr
  891.          jmp abort              ;  Unable to write out chars; abort.
  892.         mov numtry,0            ; Reset the number of tries.
  893.         mov argbk1,0            ; No data.  (Packet number still in argblk.)
  894.         mov ah,'Y'              ; Acknowledge packet.
  895.         call spack              ; Send the packet.
  896.         ret
  897. rdata2: cmp ah,'F'              ; Start of file?
  898.         jne rdata3              ;  No, try next type.
  899.         cmp oldtry,maxtry       ; Have we reached the maximum number of tries?
  900.         jl rdat21               ; If not proceed.
  901.         call erpos              ; Position cursor.
  902.         mov dx,offset ermes8
  903.         mov ah,prstr
  904.         int dos                 ; Print an error message.
  905.         jmp abort               ; Change the state to abort.
  906. rdat21: inc oldtry              ; Save the updated number of tries.
  907.         mov ax,pktnum
  908.         cmp ax,argblk           ; Is the packet's number one less than now?
  909.         je rdat22
  910.         jmp nak                 ; No, NAK it and try again.
  911. rdat22: call rtpos              ; Position cursor.
  912.         inc numrtr              ; Increment the number of retries
  913.         mov ax,numrtr
  914.         call nout               ; Write the number of retries.
  915.         mov numtry,0            ; Reset number of tries.
  916.         mov argbk1,0            ; No data.  (The packet number is in argblk.)
  917.         mov ah,'Y'              ; Acknowledge packet.
  918.         call spack              ; Send the packet.
  919.         ret
  920. rdata3: cmp ah,'Z'              ; Is it a EOF packet?
  921.         jne rdata4              ; Try and see if its an error.
  922.         mov ax,pktnum           ; Get the present packet number.
  923.         cmp ax,argblk           ; Is the packet's number correct?
  924.         je rdat32
  925.         jmp nak                 ; No, NAK it and try again.
  926. rdat32: inc ax                  ; Increment the packet number.
  927.         and ax,3FH              ; Turn off the two high order bits.
  928.         mov pktnum,ax           ; Save modulo 64 of the number.
  929.         inc numpkt
  930. rdat33: mov bx,bufpnt           ; Get the dma pointer.
  931.         mov ax,80H
  932.         sub ax,chrcnt           ; Get the number of chars left in the DMA.
  933.         mov cl,'Z'-100O         ; Put in a ^Z for EOF.
  934.         mov [bx],cl
  935.         inc ax
  936.         dec chrcnt
  937.         mov cx,chrcnt
  938.         mov temp,cx
  939.         inc bx
  940. rdt3:   inc ax
  941.         cmp ax,80H
  942.         jg rdat35               ; Pad till full.
  943.         mov cl,0                ; Use nulls.
  944.         mov [bx],cl
  945.         inc bx
  946.         jmp rdt3
  947. rdat35: call outbuf             ; Output the last buffer.
  948.          jmp abort              ;  Give up if the disk is full.
  949.         call fixfcb
  950.         mov ah,closf            ; Close up the file.
  951.         mov dx,offset fcb
  952.         int dos
  953.         mov ah,numtry           ; Get the number of tries.
  954.         mov oldtry,ah           ; Save it.
  955.         mov numtry,0            ; Reset the number of tries.
  956.         mov argbk1,0            ; No data.  (The packet number is in argblk.)
  957.         mov ah,'Y'              ; Acknowledge packet.
  958.         call spack              ; Send the packet.
  959.         mov state,'F'
  960.         ret
  961. rdata4: cmp ah,'E'                      ; Is it an error packet.
  962.         je rdata5
  963.         call error
  964. rdata5: jmp abort
  965. RDATA   ENDP
  966.  
  967. FIXFCB  PROC    NEAR    
  968.         mov bx,offset fcb+18
  969.         mov di,offset filsiz
  970.         mov ax,[bx]
  971.         mov [di],ax
  972.         mov bx,offset fcb+16
  973.         mov ax,[bx]
  974.         mov 2[di],ax
  975.         mov ax,temp             ; Get number of chars in last buffer full.
  976.         sub filsiz+2,ax         ; Get real file size.
  977.         sbb filsiz,0
  978.         mov bx,offset fcb+18
  979.         mov di,offset filsiz
  980.         mov ax,[di]
  981.         mov [bx],ax
  982.         mov bx,offset fcb+16
  983.         mov ax,2[di]
  984.         mov [bx],ax
  985.         ret
  986. FIXFCB  ENDP
  987.  
  988.  
  989. ;       Send command
  990.  
  991. SEND    PROC    NEAR
  992.         mov ah,cmifi            ; Parse an input file spec.
  993.         mov dx,offset fcb       ; Give the address for the FCB.
  994.         call comnd
  995.          jmp r                  ;  Give up on bad parse.
  996. send1:  mov ah,cmcfm
  997.         call comnd              ; Get a confirm.
  998.          jmp r                  ;  Didn't get a confirm.
  999. send11: mov fcbnum,0            ; Zero the fcb list number.
  1000.         mov ah,sfirst           ; Get the first file.
  1001.         mov dx,offset fcb
  1002.         int dos
  1003.         cmp al,0FFH             ; Any found?
  1004.         jne send12
  1005.         mov ah,prstr
  1006.         mov dx,offset crlf
  1007.         int dos
  1008.         mov ah,prstr
  1009.         mov dx,offset erms15
  1010.         int dos
  1011.         ret
  1012. ;* This must all be redone for MS-DOS.  Hopefully wild card file stepping
  1013. ;* in MS-DOS works.  If so most of the following is unnecessary.
  1014. send12: 
  1015. ;*
  1016.         call init               ; Clear the line and initialize the buffers.
  1017.         mov pktnum,0            ; Set the packet number to zero.
  1018.         mov numtry,0            ; Set the number of tries to zero.
  1019.         mov numpkt,0            ; Set the number of packets to zero.
  1020.         mov numrtr,0            ; Set the number of retries to zero.
  1021.         call rtpos              ; Position cursor.
  1022.         mov ax,0
  1023.         call nout               ; Write the number of retries.
  1024.         mov state,'S'           ; Set the state to receive initiate.
  1025. send2:  mov ah,2                ; Position cursor.
  1026.         mov bh,0
  1027.         mov dx,scrst
  1028.         int bios
  1029.         mov ah,prstr            ; Be informative.
  1030.         mov dx,offset infms2
  1031.         int dos
  1032.         mov ah,2
  1033.         mov dx,scrnp
  1034.         mov bh,0
  1035.         int bios
  1036.         mov ax,numpkt
  1037.         call nout               ; Write the packet number.
  1038.         cmp state,'D'           ; Are we in the data send state?
  1039.         jne send3
  1040.         call sdata
  1041.         jmp send2
  1042. send3:  cmp state,'F'           ; Are we in the file send state?
  1043.         jne send4
  1044.         call sfile              ; Call send file.
  1045.         jmp send2
  1046. send4:  cmp state,'Z'           ; Are we in the EOF state?
  1047.         jne send5
  1048.         call seof
  1049.         jmp send2
  1050. send5:  cmp state,'S'           ; Are we in the send initiate state?
  1051.         jne send6
  1052.         call sinit
  1053.         jmp send2
  1054. send6:  cmp state,'B'           ; Are we in the eot state?
  1055.         jne send7
  1056.         call seot
  1057.         jmp send2
  1058. send7:  cmp state,'C'           ; Are we in the send complete state?
  1059.         jne send8
  1060.         mov ah,2                ; Position cursor.
  1061.         mov dx,scrst
  1062.         mov bh,0
  1063.         int bios
  1064.         mov dx,offset infms3    ; Plus a little cuteness.
  1065.         mov ah,prstr
  1066.         int dos
  1067.         mov ah,2
  1068.         mov dx,scrrpr
  1069.         mov bh,0
  1070.         int bios
  1071.         jmp rskp
  1072. send8:  mov ah,2                ; Position cursor.
  1073.         mov dx,scrst
  1074.         mov bh,0
  1075.         int bios
  1076.         mov dx,offset infms4    ; Plus a little cuteness.
  1077.         mov ah,prstr
  1078.         int dos
  1079.         mov ah,2
  1080.         mov dx,scrrpr
  1081.         mov bh,0
  1082.         int bios
  1083.         jmp rskp
  1084. SEND    ENDP
  1085.  
  1086.  
  1087. ;       Send routines
  1088.  
  1089. ;       Send initiate
  1090.  
  1091.  
  1092. SINIT   PROC    NEAR
  1093.         cmp numtry,imxtry       ; Have we reached the maximum number of tries?
  1094.         jl sinit2
  1095.         call erpos
  1096.         mov dx,offset erms14
  1097.         mov ah,prstr
  1098.         int dos                 ; Print an error message.
  1099.         jmp abort               ; Change the state to abort.
  1100. sinit2: inc numtry              ; Save the updated number of tries.
  1101.         mov bx,offset data      ; Get a pointer to our data block.
  1102.         call rpar               ; Set up the parameter information.
  1103.         xchg ah,al
  1104.         mov ah,0
  1105.         mov argbk1,ax           ; Save the number of arguments.
  1106.         mov ax,numpkt           ; Get the packet number.
  1107.         mov argblk,ax
  1108.         mov ah,'S'              ; Send initiate packet.
  1109.         call spack              ; Send the packet.
  1110.         call rpack              ; Get a packet.
  1111.          jmp r                  ;  Trashed packet don't change state, retry.
  1112.         cmp ah,'Y'              ; ACK?
  1113.         jne sinit3              ; If not try next.
  1114.         mov ax,pktnum           ; Get the packet number.
  1115.         cmp ax,argblk           ; Is it the right packet number?
  1116.         je sini22
  1117.         ret                     ; If not try again.
  1118. sini22: inc ax                  ; Increment the packet number.
  1119.         and ax,3FH              ; Turn off the two high order bits.
  1120.         mov pktnum,ax           ; Save modulo 64 of the number.
  1121.         inc numpkt              ; Increment the number of packets.
  1122.         mov ax,argbk1           ; Get the number of pieces of data.
  1123.         mov bx,offset data      ; Pointer to the data.
  1124.         call spar               ; Read in the data.
  1125.         mov ah,numtry           ; Get the number of tries.
  1126.         mov oldtry,ah           ; Save it.
  1127.         mov numtry,0            ; Reset the number of tries.
  1128.         mov state,'F'           ; Set the state to file send.
  1129.         call getfil             ; Open the file.
  1130.          jmp abort              ;  Something is wrong, die.
  1131.         ret
  1132. sinit3: cmp ah,'N'              ; NAK?
  1133.         jne sinit4              ; If not see if its an error.
  1134.         call rtpos              ; Position cursor.
  1135.         inc numrtr              ; Increment the number of retries
  1136.         mov ax,numrtr
  1137.         call nout               ; Write the number of retries.
  1138.         mov ax,pktnum           ; Get the present packet number.
  1139.         inc ax                  ; Increment.
  1140.         cmp ax,argblk           ; Get the packet's number.
  1141.         je sini32
  1142.         ret                     ; If not assume its for this packet, go again.
  1143. sini32: mov numtry,0            ; Reset number of tries.
  1144.         mov state,'F'           ; Set the state to file send.
  1145.         ret
  1146. sinit4: cmp ah,'E'              ; Is it an error packet.
  1147.         jne sinit5
  1148.         call error
  1149. sinit5: jmp abort
  1150. SINIT   ENDP
  1151.  
  1152.  
  1153.  
  1154. ;       Send file header
  1155.  
  1156. SFILE   PROC    NEAR
  1157.         cmp numtry,maxtry       ; Have we reached the maximum number of tries?
  1158.         jl sfile1
  1159.         call erpos
  1160.         mov dx,offset erms14
  1161.         mov ah,prstr
  1162.         int dos                 ; Print an error message.
  1163.         jmp abort               ; Change the state to abort.
  1164. sfile1: inc numtry              ; Increment it.
  1165.         mov datptr,offset data  ; Get a pointer to our data block.
  1166.         mov bx,offset fcb+1             ; Pointer to file name in FCB.
  1167.         mov fcbptr,bx           ; Save position in FCB.
  1168.         mov cl,0                ; Counter for chars in file name.
  1169.         mov ch,0                ; Counter for number of chars in FCB.
  1170. sfil11: cmp ch,8H               ; Ninth char?
  1171.         jne sfil12
  1172.         mov ah,'.'
  1173.         mov bx,datptr
  1174.         mov [bx],ah             ; Put dot in data packet.       
  1175.         inc bx
  1176.         mov datptr,bx           ; Save new position in data packet.
  1177.         inc cl
  1178. sfil12: inc ch
  1179.         cmp ch,0CH              ; Twelve?
  1180.         jns sfil13
  1181.         mov bx,fcbptr
  1182.         mov ah,[bx]             ; Get char of filename.
  1183.         inc bx
  1184.         mov fcbptr,bx           ; Save position in FCB.
  1185.         cmp ah,'!'              ; Is it a good char?
  1186.         jl sfil11               ; If not, get the next.
  1187.         mov bx,datptr
  1188.         mov [bx],ah             ; Put char in data buffer.
  1189.         inc cl                  ; Increment counter.
  1190.         inc bx
  1191.         mov datptr,bx           ; Save new position. 
  1192.         jmp sfil11              ; Get another char.
  1193. sfil13: mov ch,0
  1194.         mov argbk1,cx           ; Save number of char in filename.
  1195.         mov bx,datptr
  1196.         mov ah,'$'
  1197.         mov [bx],ah             ; Put dollar sign for printing.
  1198.         mov ah,2
  1199.         mov dx,scrfln   ; Put cursor in proper place.
  1200.         mov bh,0
  1201.         int bios
  1202.         call clrfln
  1203.         mov ah,prstr
  1204.         mov dx,offset data      ; Print file name.
  1205.         int dos
  1206.  
  1207.         mov ax,pktnum           ; Get the packet number.
  1208.         mov argblk,ax
  1209.         mov ah,'F'              ; File header packet.
  1210.         call spack              ; Send the packet.
  1211.         call rpack              ; Get a packet.
  1212.          jmp r                  ;  Trashed packet don't change state, retry.
  1213.         cmp ah,'Y'              ; ACK?
  1214.         jne sfile2              ; If not try next.
  1215.         mov ax,pktnum           ; Get the packet number.
  1216.         cmp ax,argblk
  1217.         je sfil14
  1218.         ret                     ; If not hold out for the right one.
  1219. sfil14: inc ax                  ; Increment the packet number.
  1220.         and ax,3FH              ; Turn off the two high order bits.
  1221.         mov pktnum,ax           ; Save modulo 64 of the number.
  1222.         inc numpkt              ; Increment the number of packets.
  1223.         mov ah,numtry           ; Get the number of tries.
  1224.         mov oldtry,ah           ; Save it.
  1225.         mov numtry,0            ; Reset the number of tries.
  1226. ;* More file I/O.  Anything to do with the CP/M FCB must be checked for MS-DOS.
  1227. sfil15: mov ah,0                ; Get a zero.
  1228.         mov bx,offset fcb
  1229.         add bx,20H
  1230.         mov [bx],ah             ; Set the record number to zero.
  1231.         mov eoflag,ah           ; Indicate not EOF.
  1232.         mov ah,0FFH
  1233.         mov filflg,ah           ; Indicate file buffer empty.
  1234.         call gtchr
  1235.          jmp sfil16             ; Error go see if its EOF.
  1236.         jmp sfil17              ; Got the chars, proceed.
  1237. sfil16: cmp ah,0FFH             ; Is it EOF?
  1238.         je sfl161
  1239.         jmp abort               ; If not give up.
  1240. sfl161: mov ah,'Z'              ; Set the state to EOF.
  1241.         mov state,ah
  1242.         ret
  1243. sfil17: mov siz,ax
  1244. ;*
  1245.         mov state,'D'           ; Set the state to data send.
  1246.         ret
  1247. sfile2: cmp ah,'N'              ; NAK?
  1248.         jne sfile3              ; Try if error packet.
  1249.         call rtpos              ; Position cursor.
  1250.         inc numrtr              ; Increment the number of retries
  1251.         mov ax,numrtr
  1252.         call nout               ; Write the number of retries.
  1253.         mov ax,pktnum           ; Get the present packet number.
  1254.         inc ax                  ; Increment.
  1255.         cmp ax,argblk           ; Is the packet's number one more than now?
  1256.         jz sfil14               ; Just as good as a ACK; go to the ACK code.
  1257.         ret                     ; If not go try again.
  1258. sfile3: cmp ah,'E'              ; Is it an error packet.
  1259.         jne sfile4
  1260.         call error
  1261. sfile4: jmp abort
  1262. SFILE   ENDP
  1263.  
  1264.  
  1265. ;       Send data
  1266.  
  1267. SDATA   PROC    NEAR
  1268.         cmp numtry,maxtry       ; Have we reached the maximum number of tries?
  1269.         jl sdata1
  1270.         call erpos
  1271.         mov dx,offset erms14
  1272.         mov ah,prstr
  1273.         int dos                 ; Print an error message.
  1274.         jmp abort               ; Change the state to abort.
  1275. sdata1: inc numtry              ; Increment it.
  1276.         mov datptr,offset data  ; Get a pointer to our data block.
  1277.         mov cbfptr,offset filbuf ; Pointer to chars to be sent.
  1278.         mov cx,1                ; First char.
  1279. sdat11: mov bx,cbfptr
  1280.         mov ah,[bx]
  1281.         inc cbfptr
  1282.         mov bx,datptr
  1283.         mov [bx],ah             ; Put the char in the data packet.
  1284.         inc datptr              ; Save position in data packet.
  1285.         inc cx                  ; Increment the count.
  1286.         cmp cx,siz              ; Have we transfered that many?
  1287.         jle sdat11              ; If not get another.
  1288.         mov ax,siz              ; Number of char in char buffer.
  1289.         mov argbk1,ax
  1290.         mov ax,pktnum           ; Get the packet number.
  1291.         mov argblk,ax
  1292.         mov ah,'D'              ; Data packet.
  1293.         call spack              ; Send the packet.
  1294.         call rpack              ; Get a packet.
  1295.          jmp r                  ;  Trashed packet don't change state, retry.
  1296.         cmp ah,'Y'              ; ACK?
  1297.         jne sdata2              ; If not try next.
  1298.         mov ax,pktnum           ; Get the packet number.
  1299.         cmp ax,argblk           ; Is it the right packet number?
  1300.         jz sdat12
  1301.         ret                     ; If not hold out for the right one.
  1302. sdat12: inc ax                  ; Increment the packet number.
  1303.         and ax,3FH              ; Turn off the two high order bits.
  1304.         mov pktnum,ax           ; Save modulo 64 of the number.
  1305.         inc numpkt              ; Increment the number of packets.
  1306.         mov ah,numtry           ; Get the number of tries.
  1307.         mov oldtry,ah           ; Save it.
  1308.         mov numtry,0            ; Reset the number of tries.
  1309.         call gtchr
  1310.          jmp sdat13             ; Error go see if its EOF.
  1311.         mov siz,ax              ; Save the size of the data gotten.
  1312.         ret
  1313. ;* File I/O.
  1314. sdat13: cmp ah,0FFH             ; Is it EOF?
  1315.         je sdt131
  1316.         jmp abort               ; If not give up.
  1317. ;*
  1318. sdt131: mov state,'Z'           ; Set the state to EOF.
  1319.         ret
  1320. sdata2: cmp ah,'N'              ; NAK?
  1321.         jne sdata3              ; See if is an error packet.
  1322.         call rtpos              ; Position cursor.
  1323.         inc numrtr              ; Increment the number of retries
  1324.         mov ax,numrtr
  1325.         call nout               ; Write the number of retries.
  1326.         mov ax,pktnum           ; Get the present packet number.
  1327.         inc ax                  ; Increment.
  1328.         cmp ax,argblk           ; Is the packet's number one more than now?
  1329.         jz sdat12               ; Just as good as ACK; goto ACK code.
  1330.         ret                     ; If not go try again.
  1331. sdata3: cmp ah,'E'              ; Is it an error packet.
  1332.         jne sdata4
  1333.         call error
  1334. sdata4: jmp abort
  1335. SDATA   ENDP
  1336.  
  1337.  
  1338. ;       Send EOF
  1339.  
  1340. SEOF    PROC    NEAR
  1341.         cmp numtry,maxtry       ; Have we reached the maximum number of tries?
  1342.         jl seof1
  1343.         call erpos              ; Position cursor.
  1344.         mov dx,offset erms14
  1345.         mov ah,prstr
  1346.         int dos                 ; Print an error message.
  1347.         jmp abort               ; Change the state to abort.
  1348. seof1:  inc numtry              ; Increment it.
  1349.         mov ax,pktnum           ; Get the packet number.
  1350.         mov argblk,ax
  1351.         mov argbk1,0            ; No data.
  1352.         mov ah,'Z'              ; EOF packet.
  1353.         call spack              ; Send the packet.
  1354.         call rpack              ; Get a packet.
  1355.          jmp r                  ;  Trashed packet don't change state, retry.
  1356.         cmp ah,'Y'              ; ACK?
  1357.         jne seof2               ; If not try next.
  1358.         mov ax,pktnum           ; Get the packet number.
  1359.         cmp ax,argblk           ; Is it the right packet number?
  1360.         jz seof12
  1361.         ret                     ; If not hold out for the right one.
  1362. seof12: inc ax                  ; Increment the packet number.
  1363.         and ax,3FH              ; Turn off the two high order bits.
  1364.         mov pktnum,ax           ; Save modulo 64 of the number.
  1365.         inc numpkt              ; Increment the number of packets.
  1366.         mov ah,numtry           ; Get the number of tries.
  1367.         mov oldtry,ah           ; Save it.
  1368.         mov numtry,0            ; Reset the number of tries.
  1369.         mov ah,closf            ; Close the file.
  1370.         mov dx,offset fcb
  1371.         int dos
  1372. ;* Check if successful
  1373.         call gtnfil             ; Get the next file.
  1374.          jmp seof13             ;  No more.
  1375.         mov state,'F'           ; Set the state to file send.
  1376.         ret
  1377. seof13: mov state,'B'           ; Set the state to EOT.
  1378.         ret
  1379. seof2:  cmp ah,'N'              ; NAK?
  1380.         jne seof3               ; Try and see if its an error packet.
  1381.         call rtpos              ; Position cursor.
  1382.         inc numrtr              ; Increment the number of retries
  1383.         mov ax,numrtr
  1384.         call nout               ; Write the number of retries.
  1385.         mov ax,pktnum           ; Get the present packet number.
  1386.         inc ax                  ; Increment.
  1387.         cmp ax,argblk           ; Is the packet's number one more than now?
  1388.         jz seof12               ; Just as good as a ACK; go to the ACK code.
  1389.         ret                     ; If not go try again.
  1390. seof3:  cmp ah,'E'              ; Is it an error packet?
  1391.         jne seof4
  1392.         call error
  1393. seof4:  jmp abort
  1394. SEOF    ENDP
  1395.  
  1396.  
  1397. ;       Send EOT
  1398.  
  1399. SEOT    PROC    NEAR
  1400.         cmp numtry,maxtry       ; Have we reached the maximum number of tries?
  1401.         jl seot1
  1402.         call erpos             ; Position cursor.
  1403.         mov dx,offset erms14
  1404.         mov ah,prstr
  1405.         int dos                 ; Print an error message.
  1406.         jmp abort               ; Change the state to abort.
  1407. seot1:  inc numtry              ; Increment it.
  1408.         mov ax,pktnum           ; Get the packet number.
  1409.         mov argblk,ax
  1410.         mov argbk1,0            ; No data.
  1411.         mov ah,'B'              ; EOF packet.
  1412.         call spack              ; Send the packet.
  1413.         call rpack              ; Get a packet.
  1414.          jmp r                  ; Trashed packet don't change state, retry.
  1415.         cmp ah,'Y'              ; ACK?
  1416.         jne seot2               ; If not try next.
  1417.         mov ax,pktnum           ; Get the packet number.
  1418.         cmp ax,argblk           ; Is it the right packet number?
  1419.         jz seot12
  1420.         ret                     ; If not hold out for the right one.
  1421. seot12: inc ax                  ; Increment the packet number.
  1422.         and ax,3FH              ; Turn off the two high order bits.
  1423.         mov pktnum,ax           ; Save modulo 64 of the number.
  1424.         inc numpkt              ; Increment the number of packets.
  1425.         mov ah,numtry           ; Get the number of tries.
  1426.         mov oldtry,ah           ; Save it.
  1427.         mov numtry,0            ; Reset the number of tries.
  1428.         mov state,'C'           ; Set the state to file send.
  1429.         ret
  1430. seot2:  cmp ah,'N'              ; NAK?
  1431.         jne seot3               ; Is it error.
  1432.         call rtpos              ; Position cursor.
  1433.         inc numrtr              ; Increment the number of retries
  1434.         mov ax,numrtr
  1435.         call nout               ; Write the number of retries.
  1436.         mov ax,pktnum           ; Get the present packet number.
  1437.         inc ax                  ; Increment.
  1438.         cmp ax,argblk           ; Is the packet's number one more than now?
  1439.         jz seot12               ; Just as good as a ACK; go to the ACK code.
  1440.         ret                     ; If not go try again.
  1441. seot3:  cmp ah,'E'              ; Is it an error packet.
  1442.         jne seot4
  1443.         call error
  1444. seot4:  jmp abort
  1445. SEOT    ENDP
  1446.  
  1447.  
  1448. ;* Here is the bulk of the file I/O.  Good luck.
  1449.  
  1450. ;       File routines
  1451.  
  1452. ;       Output the chars in a packet.
  1453.  
  1454. FILEIO  PROC    NEAR    
  1455.  
  1456. ptchr:  mov temp1,ax            ; Save the size.
  1457.         mov bx,offset data      ; Beginning of received packet data.
  1458.         mov outpnt,bx           ; Remember where we are.
  1459.         mov ch,rquote           ; Quote char.
  1460. ptchr1: dec temp1               ; Decrement # of chars in packet.
  1461.         jnl pt1
  1462.         jmp rskp                ; Return successfully if done.
  1463. pt1:    dec chrcnt              ; Decrement number of chars in dta.
  1464.         jns ptchr2              ; Continue if space left.
  1465.         call outbuf             ; Output it if full.
  1466.          jmp r                  ;  Error return if disk is full.
  1467. ptchr2: mov bx,outpnt           ; Get position in output buffer.
  1468.         mov ah,[bx]                     ; Grab a char.
  1469.         inc bx
  1470.         mov outpnt,bx           ; and bump pointer.
  1471.         cmp ah,ch               ; Is it the quote char?
  1472.         jne ptchr4              ; If not proceed.
  1473.         mov ah,[bx]                     ; Get the quoted character
  1474.         inc bx
  1475.         mov outpnt,bx           ; and bump pointer.
  1476.         dec temp1               ; Decrement # of chars in packet.
  1477.         mov dh,ah               ; Save the char.
  1478.         and ah,80H                      ; Turn off all but the parity bit.
  1479.         mov dl,ah               ; Save the parity bit.
  1480.         mov ah,dh                       ; Get the char.
  1481.         and ah,7FH                      ; Turn off the parity bit.
  1482.         cmp ah,ch               ; Is it the quote char?
  1483.         jz ptchr3               ; If so just go write it out.
  1484.         mov ah,dh                       ; Get the char.
  1485.         add ah,40H                      ; Make it a control char again.
  1486.         and ah,7FH                      ; Modulo 128.
  1487. ptchr3: or ah,dl                ; Or in the parity bit.
  1488. ptchr4: mov bx,bufpnt           ; Destination buffer.
  1489.         mov [bx],ah                     ; Store it.
  1490.         inc bx
  1491.         mov bufpnt,bx           ; Update the pointer
  1492.         jmp ptchr1              ; and loop to next char.
  1493.  
  1494.  
  1495.         ; output the buffer, reset bufpnt and chrcnt
  1496.  
  1497. outbuf: push bx
  1498.         mov ah,writef           ; The write code.
  1499.         mov dx,offset fcb
  1500.         int dos                  ; Write the record.
  1501.         pop bx
  1502.         cmp al,0                        ; Successful.
  1503.         jz outbf1
  1504.         cmp al,01
  1505.         jz outbf0
  1506.         call erpos
  1507.         mov ah,prstr
  1508.         mov dx,offset erms19    ; Record length exceeds dta.
  1509.         int dos
  1510.         ret
  1511. outbf0: call erpos
  1512.         mov ah,prstr            ; Tell about it.
  1513.         mov dx,offset erms11    ; Disk full error.
  1514.         int dos
  1515.         ret
  1516. outbf1: mov bx,offset buff      ; Addr for beginning.
  1517.         mov bufpnt,bx           ; Store addr for beginning.
  1518.         mov ax,bufsiz-1         ; Buffer size.
  1519.         mov chrcnt,ax           ; Number of chars left.
  1520.         jmp rskp
  1521.  
  1522.  
  1523. ;       Get the chars from the file.
  1524.  
  1525. gtchr:  mov ch,squote           ; Keep quote char in c.
  1526.         mov ah,filflg           ; Get the file flag.
  1527.         cmp ah,0                        ; Is there anything in the DMA?
  1528.         jz gtchr0               ; Yup, proceed.
  1529.         mov cl,0                ; No chars yet.
  1530.         call inbuf
  1531.          jmp gtceof             ; No more chars, go return EOF.
  1532. gtchr0: mov al,spsiz            ; Get the maximum packet size.
  1533.         sub al,5                ; Subtract the overhead.
  1534.         mov ah,0
  1535.         mov temp1,ax            ; Number of chars we're to get.
  1536.         mov bx,offset filbuf            ; Where to put the data.
  1537.         mov cbfptr,bx           ; Remember where we are.
  1538.         mov cl,0                ; No chars.
  1539. gtchr1: dec temp1               ; Decrement the number of chars left.
  1540.         jns gtchr2              ; Go on if there is more than one left.
  1541.         mov al,cl                       ; Return the count in A.
  1542.         mov ah,0
  1543.         jmp rskp
  1544. gtchr2: mov ax,chrcnt
  1545.         dec ax
  1546.         jl gtchr3
  1547.         mov chrcnt,ax
  1548.         jmp gtchr4
  1549. gtchr3: call inbuf              ; Get another buffer full.
  1550.          jmp gtceof
  1551.         cmp chrcnt,0
  1552.         jne gtchr4
  1553.         sub cl,2                ; Don't count controllified Z.
  1554.         mov al,cl
  1555.         mov ah,0
  1556.         jmp rskp
  1557. gtchr4: mov bx,bufpnt           ; Position in DMA.
  1558.         mov ah,[bx]                     ; Get a char from the file.
  1559.         inc bx
  1560.         mov bufpnt,bx
  1561.         mov dh,ah               ; Save the char.
  1562.         and ah,80H                      ; Turn off all but parity.
  1563.         mov dl,ah               ; Save the parity bit.
  1564.         mov ah,dh                       ; Restore the char.
  1565.         and ah,7FH                      ; Turn off the parity.
  1566.         cmp ah,' '                      ; Compare to a space.
  1567.         jl gtchr5               ; If less then its a control char, handle it.
  1568.         cmp ah,del                      ; Is the char a delete?
  1569.         jz gtchr5               ; Go quote it.
  1570.         cmp ah,ch               ; Is it the quote char?
  1571.         jne gtchr8              ; If not proceed.
  1572.         dec temp1               ; Decrement the char total remaining.
  1573.         mov bx,cbfptr           ; Position in character buffer.
  1574.         mov [bx],ah                     ; Put the char in the buffer.
  1575.         inc bx
  1576.         mov cbfptr,bx
  1577.         inc cl                  ; Increment the char count.
  1578.         jmp gtchr8
  1579. gtchr5: or ah,dl                ; Turn on the parity bit.
  1580.         cmp ah,('Z'-100O)               ; Is it a ^Z?
  1581.         jne gtchr7              ; If not just proceed.
  1582.         mov ah,eoflag           ; EOF flag set?
  1583.         cmp ah,0
  1584.         jz gtchr6               ; If not just go on.
  1585.         mov bx,bufpnt
  1586.         mov ax,chrcnt
  1587.         mov dh,al               ; Get number of chars left in DMA.
  1588. gtch51: dec dh
  1589.         mov ah,dh
  1590.         jns gtch52              ; Any chars left?
  1591.         mov chrcnt,0            ; If not, say so.
  1592.         mov al,cl                       ; Return the count in A.
  1593.         mov ah,0
  1594.         jmp rskp
  1595. gtch52: mov ah,[bx]                     ; Get the next char.
  1596.         inc bx                  ; Move the pointer.
  1597.         cmp ah,('Z'-100O)               ; Is it a ^Z?
  1598.         jz gtch51               ; If so see if they rest are.
  1599.  
  1600. gtchr6: mov ah,('Z'-100O)       ; Restore the ^Z.
  1601. gtchr7: xchg ah,al
  1602.         mov ah,0
  1603.         mov temp2,ax            ; Save the char.
  1604.         dec temp1               ; Decrement char counter.
  1605.         mov bx,cbfptr           ; Position in character buffer.
  1606.         mov [bx],ch                     ; Put the quote in the buffer.
  1607.         inc bx
  1608.         mov cbfptr,bx
  1609.         inc cl                  ; Increment the char count.
  1610.         mov ax,temp2            ; Get the control char back.
  1611.         xchg al,ah
  1612.         add ah,40H                      ; Make the non-control.
  1613.         and ah,7fH                      ; Modulo 200 octal.
  1614. gtchr8: mov bx,cbfptr           ; Position in character buffer.
  1615.         or ah,dl                ; Or in the parity bit.
  1616.         mov [bx],ah                     ; Put the char in the buffer.
  1617.         inc bx
  1618.         mov cbfptr,bx
  1619.         inc cl                  ; Increment the char count.
  1620.         jmp gtchr1              ; Go around again.
  1621.  
  1622. gtceof: cmp cl,0                ; Had we gotten any data?
  1623.         je gteof0               ; Nope.
  1624.         mov al,cl
  1625.         mov ah,0
  1626.         jmp rskp
  1627. gteof0: mov ah,0FFH             ; Get a minus one.
  1628.         ret
  1629.  
  1630.  
  1631. inbuf:  mov ah,eoflag           ; Have we reached the end?
  1632.         cmp ah,0
  1633.         jz inbuf0
  1634.         ret                     ; Return if set.
  1635. inbuf0: push bx                 
  1636.         push cx
  1637.         mov bx,offset buff      ; Set the r/w buffer pointer.
  1638.         mov bufpnt,bx
  1639.         mov ah,readf            ; Read a record.
  1640.         mov dx,offset fcb
  1641.         int dos
  1642.         mov cx,filsiz
  1643.         cmp cx,0                ; Check for 128 chars or less left.
  1644.         jne inbuf1              ; Still have data left.
  1645.         mov ax,ds
  1646.         mov es,ax
  1647.         mov si,offset filsiz+2
  1648.         mov di,offset bufhex
  1649.         cmps filsiz+2,es:bufhex
  1650.         ja inbuf1               ; More than 128 chars.
  1651.         mov eoflag,0FFH         ; Set End-of-file.
  1652.         mov cx,filsiz+2
  1653.         mov chrcnt,cx           ; Return proper number of chars.
  1654.         mov filflg,0            ; Buffer not empty.
  1655.         pop cx
  1656.         pop bx
  1657.         jmp rskp
  1658. inbuf1: sub filsiz+2,80H        ; Sent another 128 chars.
  1659.         sbb filsiz,0            ; Account for the doubleword.
  1660.         mov al,80H              ; Use as counter for number of chars read.
  1661.         pop cx
  1662.         pop bx
  1663.         cmp filflg,0            ; Ever used DMS?
  1664.         jnz inbf21              ; Nope, then don't change count.
  1665.         dec al                  ; Fix boundary error.
  1666. inbf21: mov ah,0                ; Zero the flag (buffer not empty).
  1667.         mov chrcnt,ax           ; Number of chars read from file.
  1668.         mov filflg,0            ; Buffer not empty.
  1669.         jmp rskp
  1670.  
  1671. getfil: mov ah,0FFH
  1672.         mov filflg,ah           ; Nothing in the DMA.
  1673.         mov ax,0
  1674.         mov eoflag,ah           ; Not the end of file.
  1675.         mov bx,offset fcb+0CH
  1676.         mov [bx],ax             ; Zero the current block number.
  1677.         mov bx,offset fcb+0EH
  1678.         mov [bx],ax             ; Ditto for Lrecl.
  1679.         mov bx,offset fcb+20H
  1680.         mov [bx],ah             ; Zero the current record (of block).
  1681.         inc bx
  1682.         mov [bx],ax             ; Same for record (of file). 
  1683.         mov bx,offset fcb+23H
  1684.         mov [bx],ax
  1685.         mov ah,openf            ; Open the file.
  1686.         mov dx,offset fcb
  1687.         int dos
  1688.         mov bx,offset fcb+18    ; File size in bytes (hi order word).
  1689.         mov di,offset filsiz    ; Where to put the info. 
  1690.         mov ax,[bx]
  1691.         mov [di],ax
  1692.         mov bx,offset fcb+16    ; Lo order word.
  1693.         mov ax,[bx]
  1694.         mov 2[di],ax
  1695.         sub filsiz+2,1          ; Don't count the ^Z.
  1696.         sbb filsiz,0
  1697.         jmp rskp
  1698.  
  1699.  
  1700. gtnfil: ret                     ; Just need label for now.
  1701.  
  1702. ;       Get the file name (including host to micro translation)
  1703.  
  1704. gofil:  mov bx,offset data      ; Get the address of the file name.
  1705.         mov datptr,bx           ; Store the address.
  1706.         mov bx,offset fcb+1            ; Address of the FCB.
  1707.         mov fcbptr,bx           ; Save it.
  1708.         mov ax,0
  1709.         mov temp1,ax            ; Initialize the char count.
  1710.         mov temp2,ax
  1711.         mov si,offset fcb
  1712.         mov [si],ah             ; Set the drive to default to current.
  1713.         mov ch,' '
  1714. gofil1: mov [bx],ch                     ; Blank the FCB.
  1715.         inc bx
  1716.         inc ah
  1717.         cmp ah,0BH                      ; Twelve?
  1718.         jl gofil1
  1719. gofil2: mov bx,datptr           ; Get the NAME field.
  1720.         mov ah,[bx]
  1721.         inc bx
  1722.         mov datptr,bx
  1723.         cmp ah,'.'                      ; Seperator?
  1724.         jne gofil3
  1725.         mov bx,offset fcb+9H
  1726.         mov fcbptr,bx
  1727.         mov ax,temp1
  1728.         mov temp2,ax
  1729.         mov temp1,9H
  1730.         jmp gofil6
  1731. gofil3: cmp ah,0                        ; Trailing null?
  1732.         jz gofil7               ; Then we're done.
  1733.         mov bx,fcbptr
  1734.         mov [bx],ah
  1735.         inc bx
  1736.         mov fcbptr,bx
  1737.         mov ax,temp1            ; Get the char count.
  1738.         inc ax
  1739.         mov temp1,ax
  1740.         cmp ax,8H                       ; Are we finished with this field?
  1741.         jl gofil2
  1742. gofil4: mov temp2,ax
  1743.         mov bx,datptr
  1744.         mov ah,[bx]
  1745.         inc bx
  1746.         mov datptr,bx
  1747.         cmp ah,0
  1748.         jz gofil7
  1749.         cmp ah,'.'                      ; Is this the terminator?
  1750.         jne gofil4              ; Go until we find it.
  1751. gofil6: mov bx,datptr           ; Get the TYPE field.
  1752.         mov ah,[bx]
  1753.         inc bx
  1754.         mov datptr,bx
  1755.         cmp ah,0                        ; Trailing null?
  1756.         jz gofil7               ; Then we're done.
  1757.         mov bx,fcbptr
  1758.         mov [bx],ah
  1759.         inc bx
  1760.         mov fcbptr,bx
  1761.         inc temp1               ; Increment char count.
  1762.         cmp temp1,0CH                   ; Are we finished with this field?
  1763.         jl gofil6
  1764. gofil7: mov bx,datptr
  1765.         mov ah,'$'
  1766.         mov [bx],ah             ; Put in a dollar sign for printing.
  1767.         mov ah,2                ; Position cursor.
  1768.         mov dx,scrfln
  1769.         mov bh,0
  1770.         int bios
  1771.         call clrfln
  1772.         mov ah,prstr            ; Print the file name.
  1773.         mov dx,offset data
  1774.         int dos
  1775.         mov ah,flwflg           ; Is file warning on?
  1776.         cmp ah,0
  1777.         jnz gf7x
  1778.         jmp gofil9              ; If not, just proceed.
  1779. gf7x:   mov ah,openf            ; See if the file exists.
  1780.         mov dx,offset fcb
  1781.         int dos
  1782.         cmp al,0FFH             ; Does it exist?
  1783.         jnz gf8x
  1784.         jmp gofil9               ; If not create it.
  1785. gf8x:   mov ah,2                ; Position cursor.
  1786.         mov dx,scrfr
  1787.         mov bh,0
  1788.         int bios
  1789.         mov ah,prstr            ; Inform the user we are renaming the file.
  1790.         mov dx,offset infms5
  1791.         int dos
  1792.         mov ax,temp2            ; Get the number of chars in the file name.
  1793.         cmp ax,0
  1794.         jne gofil8
  1795.         mov ax,temp1
  1796.         mov temp2,ax
  1797. gofil8: mov ch,0
  1798.         mov cl,al
  1799.         mov al,0                        ; Says if first field is full.
  1800.         cmp cl,9H                       ; Is the first field full?
  1801.         jne gofl81
  1802.         mov al,0FFH             ; Set a flag saying so.
  1803.         dec cl
  1804. gofl81: mov bx,offset fcb              ; Get the FCB.
  1805.         add bx,cx               ; Add in the character number.
  1806.         mov ah,'&'
  1807.         mov [bx],ah             ; Replace the char with an ampersand.
  1808.         push ax
  1809.         push bx
  1810.         mov ah,openf            ; See if the file exists.
  1811.         mov dx,offset fcb
  1812.         int dos
  1813.         pop bx
  1814.         cmp al,0FFH             ; Does it exist?
  1815.         pop ax
  1816.         jz gofl89               ; If not create it.
  1817.         cmp al,0                      ; Get the flag.
  1818.         jz gofl83
  1819.         dec cl                  ; Decrement the number of chars.
  1820.         cmp cl,0
  1821.         jz gofl88               ; If no more, die.
  1822.         jmp gofl81
  1823. gofl83: inc cl                  ; Increment the number of chars.
  1824.         cmp cl,9H                       ; Are we to the end?
  1825.         jl gofl81               ; If not try again ; else fail. 
  1826.  
  1827. gofl88: call erpos              ; Position cursor.
  1828.         mov ah,prstr            ; Tell the user that we can't rename it.
  1829.         mov dx,offset ermes4
  1830.         int dos
  1831.         ret
  1832.  
  1833. gofl89: mov bx,offset fcb+0CH          ; Point past the end of the file name.
  1834.         mov dh,[bx]                     ; Save the present contents.
  1835.         mov ah,'$'
  1836.         mov [bx],ah             ; Put in a dollar sign.
  1837.         push dx
  1838.         mov ah,prstr            ; Print the file name.
  1839.         mov dx,offset fcb+1
  1840.         int dos
  1841.         pop dx
  1842.         mov bx,offset fcb+0CH          ; Restore over the dollar sign.
  1843.         mov [bx],dh
  1844. gofil9: mov ah,delf             ; Delete the file if it exists.
  1845.         mov dx,offset fcb
  1846.         int dos
  1847.         mov ax,0
  1848.         mov si,offset fcb+0CH
  1849.         mov [si],ax             ; Zero current block.
  1850.         mov si,offset fcb+0EH
  1851.         mov [si],ax             ; Same for Lrecl.
  1852.         mov si,offset fcb+20H
  1853.         mov [si],ah             ; Zero the current record (within block).
  1854.         inc si
  1855.         mov [si],ax             ; Zero record (within file).
  1856.         mov si,offset fcb+23H
  1857.         mov [si],ax
  1858.         mov ah,makef            ; Now create it.
  1859.         mov dx,offset fcb
  1860.         int dos
  1861.         cmp al,0FFH             ; Is the disk full?
  1862.         je gf9x
  1863.         jmp rskp
  1864. gf9x:   call erpos              ; Position cursor.
  1865.         mov ah,prstr            ; If so tell the user.
  1866.         mov dx,offset erms11
  1867.         int dos
  1868.         ret
  1869.  
  1870. FILEIO  ENDP
  1871. ;*
  1872.  
  1873.  
  1874. ;       Packet routines
  1875.  
  1876. ; Send_Packet
  1877. ; This routine assembles a packet from the arguments given and sends it
  1878. ; to the host.
  1879. ;
  1880. ; Expects the following:
  1881. ;       AH     - Type of packet (D,Y,N,S,R,E,F,Z,T)
  1882. ;       ARGBLK - Packet sequence number
  1883. ;       ARGBK1 - Number of data characters
  1884. ; Returns: +1 always
  1885.  
  1886. SPKT    PROC    NEAR
  1887.  
  1888. spack:  push ax                 ; Save the packet type.
  1889.         mov bx,offset packet    ; Get address of the send packet.
  1890.         mov ah,soh              ; Get the start of header char.
  1891.         mov [bx],ah             ; Put in the packet.
  1892.         inc bx                  ; Point to next char.
  1893.         mov ax,argbk1           ; Get the number of data chars.
  1894.         xchg ah,al
  1895.         add ah,' '+3            ; Real packet character count made printable.
  1896.         mov [bx],ah             ; Put in the packet.
  1897.         inc bx                  ; Point to next char.
  1898.         mov cl,ah               ; Start the checksum.
  1899.         mov ax,argblk           ; Get the packet number.
  1900.         xchg ah,al
  1901.         add ah,' '              ; Add a space so the number is printable.
  1902.         mov [bx],ah             ; Put in the packet.
  1903.         inc bx                  ; Point to next char.
  1904.         add cl,ah               ; Add the packet number to the checksum.
  1905.         pop ax                  ; Get the packet type.
  1906.         mov [bx],ah             ; Put in the packet.
  1907.         inc bx                  ; Point to next char.
  1908.         add cl,ah               ; Add the type to the checksum.
  1909.         mov dx,argbk1           ; Get the packet size.
  1910. spack2: cmp dx,0                ; Are there any chars of data?
  1911.          jz spack3              ;  No, finish up.
  1912.         dec dx                  ; Decrement the char count.
  1913.         mov ah,[bx]             ; Get the next char.
  1914.         inc bx                  ; Point to next char.
  1915.         add cl,ah               ; Add the char to the checksum.
  1916.         cmp ah,0
  1917.         jns spack2
  1918.         mov hierr,0FFH          ; set err flag. 
  1919.         jmp spack2              ; Go try again.
  1920. spack3: cmp hierr,0
  1921.         je sp3x                 ; Nothing special to do.
  1922.         call biterr
  1923.         mov hierr,0             ; Reset.
  1924. sp3x:   mov ah,cl               ; Get the character total.
  1925.         mov ch,cl               ; Save here too (need 'cl' for shift).
  1926.         and ah,0C0H             ; Turn off all but the two high order bits.
  1927.         mov cl,6
  1928.         shr ah,cl               ; Shift them into the low order position.
  1929.         mov cl,ch
  1930.         add ah,cl               ; Add it to the old bits.
  1931.         and ah,3FH              ; Turn off the two high order bits.  (MOD 64)
  1932.         add ah,' '              ; Add a space so the number is printable.
  1933.         mov [bx],ah             ; Put in the packet.
  1934.         inc bx                  ; Point to next char.
  1935.         mov ah,seol             ; Get the EOL the other host wants.
  1936.         mov [bx],ah             ; Put in the packet.
  1937.         inc bx                  ; Point to next char.
  1938.         mov ah,0                ; Get a null.
  1939.         mov [bx],ah             ; Put in the packet.
  1940.         cmp debug,0             ; debug mode.
  1941.         je spack4
  1942.         inc bx
  1943.         mov ah,'$'
  1944.         mov [bx],ah
  1945.         mov ah,2
  1946.         mov dx,scrsp
  1947.         mov bh,0
  1948.         int bios
  1949.         mov ah,prstr
  1950.         mov dx,offset spmes
  1951.         int dos
  1952.         mov dx,offset packet
  1953.         mov ah,prstr
  1954.         int dos                 ; debug end.
  1955. spack4: call outpkt             ; Call the system dependent routine.
  1956.         ret
  1957.  
  1958. SPKT    ENDP 
  1959. ;       Write out a packet.
  1960.  
  1961. OUTPKT  PROC    NEAR
  1962.         mov dh,spad             ; Get the number of padding chars.
  1963. outpk2: dec dh
  1964.         cmp dh,0
  1965.         jl outpk3               ; If none left proceed.
  1966.         mov ah,spadch           ; Get the padding char.
  1967.         call outchr             ; Output it.
  1968.         jmp outpk2
  1969. outpk3: mov bx,offset packet    ; Point to the packet.
  1970. outlup: mov ah,[bx]             ; Get the next character.
  1971.         cmp ah,0                ; Is it a null?
  1972.         jnz outlp2
  1973.         ret
  1974. outlp2: call outchr             ; Output the character.
  1975.         inc bx                  ; Increment the char pointer.
  1976.         jmp outlup
  1977. OUTPKT  ENDP
  1978.  
  1979.  
  1980. ;************************System Dependent****************************
  1981. ;       Put a char in AH to the port.
  1982. PORT    PROC  NEAR 
  1983. outchr: mov al,ah               ; Char must be in al.
  1984.         mov cx,0
  1985.         cmp ibmflg,0
  1986.         je outch1
  1987.         or al,080H
  1988. outch1: mov ah,1                ; Output it.
  1989.         mov dx,0
  1990.         int comm
  1991.         cmp ah,00H
  1992.         je outch3
  1993.         loop outch1
  1994.         ret
  1995. outch3: ret
  1996. ;       cmp ibmflg,0
  1997. ;       je outch2               ; Only wait for the IBM.
  1998. ;       cmp al,CR
  1999. ;       je outch2
  2000. ;       mov cx,0A00H
  2001. ;clup:  loop clup       
  2002. ;outch2:        ret
  2003.  
  2004.  
  2005. ;************************System Dependent****************************
  2006. ;
  2007. ;       Get a char from the port and return in A.
  2008.  
  2009. inchr:  mov dx,03FDH            ; Get port status.
  2010.         in al,dx
  2011.         test al,1               ; Data available?
  2012.         jnz inchr3              ; Read char ok.
  2013.         mov ah,constat          ; Is a char on the console?
  2014.         int dos
  2015.         cmp al,0
  2016.         jz inchr                ; If not go look for another char.
  2017.         mov ah,conin            ; Get the char.
  2018.         int dos
  2019.         mov ah,al 
  2020.         cmp ah,cr                       ; Is it a carriage return?
  2021.         je inchr4              ; If not go look for another char.
  2022.         jmp inchr               ; Wait for some kind of input.
  2023. inchr4: ret
  2024. inchr3: mov dx,03F8H            ; Read in the char.
  2025.         in al,dx
  2026.         mov ah,al
  2027.         cmp ibmflg,0
  2028.         je inchr5
  2029.         and ah,7FH                      ; Turn off the parity bit.
  2030. inchr5: jmp rskp
  2031. PORT    ENDP
  2032. ;*
  2033.  
  2034.  
  2035. ; Receive_Packet
  2036. ; This routine waits for a packet arrive from the host.  It reads
  2037. ; chars until it finds a SOH.
  2038.  
  2039. RPACK   PROC    NEAR
  2040.         mov ah,2
  2041.         mov dx,scrst            ; Position cursor.
  2042.         mov bh,0
  2043.         int bios
  2044.         mov ah,prstr
  2045.         mov dx,offset infms0
  2046.         int dos
  2047.         call inpkt              ; Read up to a carriage return.
  2048.          jmp r                  ;  Return bad.
  2049. rpack0: call getchr             ; Get a character.
  2050.          jmp r                  ;  Hit the carriage return, return bad.
  2051.         cmp ah,soh              ; Is the char the start of header char?
  2052.          jne rpack0             ;  No, go until it is.
  2053. rpack1: call getchr             ; Get a character.
  2054.          jmp r                  ;  Hit the carriage return, retuset infms0
  2055.         cmp ah,soh              ; Is the char the start of header char?
  2056.          jz rpack1              ;  Yes, then go start over.
  2057.         mov cl,ah               ; Start the checksum.
  2058.         sub ah,' '+3            ; Get the real data count.
  2059.         mov dh,ah               ; Save it for later.
  2060.         mov al,ah               ; Swap halves.
  2061.         mov ah,0
  2062.         mov argbk1,ax           ; Save the data count.
  2063.         call getchr             ; Get a character.
  2064.          jmp r                  ;  Hit the carriage return, return bad.
  2065.         cmp ah,soh              ; Is the char the start of header char?
  2066.          jz rpack1              ;  Yes, then go start over.
  2067.         add cl,ah               ; Add it to the checksum.
  2068.         sub ah,' '              ; Get the real packet number.
  2069.         mov al,ah               ; Swap halves.
  2070.         mov ah,0
  2071.         mov argblk,ax           ; Save the packet number.
  2072.         call getchr             ; Get a character.
  2073.          jmp r                  ;  Hit the carriage return, return bad.
  2074.         cmp ah,soh              ; Is the char the start of header char?
  2075.          jz rpack1              ;  Yes, then go start over.
  2076.         push ax                 ; Save the message type.
  2077.         add cl,ah               ; Add it to the checksum.
  2078.         mov bx,offset data      ; Point to the data buffer.
  2079. rpack2: dec dh                  ; Any data characters?
  2080.          js rpack3              ;  If not go get the checksum.
  2081.         call getchr             ; Get a character.
  2082.          jmp r                  ;  Hit the carriage return, return bad.
  2083.         cmp ah,soh              ; Is the char the start of header char?
  2084.          jz rpack1              ;  Yes, then go start over.
  2085.         mov [bx],ah             ; Put the char into the packet.
  2086.         inc bx                  ; Point to the next character.
  2087.         add cl,ah               ; Add it to the checksum.
  2088.         jmp rpack2              ; Go get another.
  2089. rpack3: call getchr             ; Get a character.
  2090.          jmp r                  ;  Hit the carriage return, return bad.
  2091.         cmp ah,soh              ; Is the char the start of header char?
  2092.          jz rpack1              ;  Yes, then go start over.
  2093.         sub ah,' '              ; Turn the char back into a number.
  2094.         mov dh,cl               ; Get the character total.
  2095.         and dh,0C0H             ; Turn off all but the two high order bits.
  2096.         mov ch,cl
  2097.         mov cl,6
  2098.         shr dh,cl               ; Shift them into the low order position.
  2099.         mov cl,ch
  2100.         add dh,cl               ; Add it to the old bits.
  2101.         and dh,3FH              ; Turn off the two high order bits.  (MOD 64)
  2102.         cmp dh,ah               ; Are they equal?
  2103.          jz rpack4              ;  If so finish up.
  2104.         mov dx,offset dimsg1
  2105.         mov ah,prstr
  2106.         int dos                 ; Print a diagnostic message.
  2107.         ret
  2108. rpack4: mov ah,0
  2109.         mov [bx],ah             ; Put a null at the end of the data.
  2110.         pop ax                  ; Get the type.
  2111.         jmp rskp
  2112. RPACK   ENDP
  2113.  
  2114.  
  2115. INPKT   PROC    NEAR
  2116.         mov bx,offset recpkt    ; Point to the beginning of the packet.
  2117.         mov incnt,0
  2118. inpkt2: call inchr              ; Get a character.
  2119.          jmp r                  ;  Return failure.
  2120.         mov [bx],ah             ; Put the char in the packet.
  2121.         inc bx
  2122.         inc incnt
  2123.         cmp ah,reol             ; Is it the EOL char?
  2124.         jne inpkt2              ; If not loop for another.
  2125.         cmp ibmflg,0            ; Is this the (dumb) IBM mainframe?
  2126.         jz inpkt4               ; If not then proceed.
  2127.         cmp incnt,1             ; Ignore bare CR.
  2128.         jne inpkt5
  2129.         mov incnt,0
  2130.         mov bx,offset recpkt
  2131.         jmp inpkt2
  2132. inpkt5: cmp state,'S'           ; Check if this is the Send-Init packet.
  2133.         jz inpkt4               ; If so don't wait for the XON.
  2134. inpkt3: call inchr              ; Wait for the turn around char.
  2135.          jmp inpkt4
  2136.         cmp ah,xon              ; Is it the IBM turn around character?
  2137.         jne inpkt3              ; If not, go until it is.
  2138. inpkt4: mov bx,offset recpkt
  2139.         mov pktptr,bx           ; Save the packet pointer.
  2140.         jmp rskp                ; If so we are done.
  2141. INPKT   ENDP
  2142.  
  2143.  
  2144. GETCHR  PROC    NEAR
  2145.         push bx
  2146.         mov bx,pktptr           ; Get the packet pointer.
  2147.         mov ah,[bx]             ; Get the char.
  2148.         inc bx
  2149.         mov pktptr,bx
  2150.         pop bx                  ; Restore BX.
  2151.         cmp ah,reol             ; Is it the EOL char?
  2152.         jne getcr2              ; If not return retskp.
  2153.         ret                     ; If so return failure.
  2154. getcr2: jmp rskp
  2155. GETCHR  ENDP
  2156.  
  2157.  
  2158. ; This is where we go if we get an error packet.
  2159.  
  2160. ERROR   PROC    NEAR
  2161.         mov state,'A'           ; Set the state to abort.
  2162.         call erpos              ; Position the cursor.
  2163.         mov bx,argbk1           ; Get the length of the data.
  2164.         add bx,offset data      ; Get to the end of the string.
  2165.         mov ah,'$'              ; Put a dollar sign at the end.
  2166.         mov [bx],ah
  2167.         mov ah,prstr            ; Print the error message.
  2168.         mov dx,offset data
  2169.         int dos
  2170.         ret
  2171. ERROR   ENDP
  2172.  
  2173.  
  2174. ; This is the 'exit' command.  It leaves KERMIT and returns to CP/M.
  2175.  
  2176. EXIT    PROC    NEAR
  2177.         mov ah,cmcfm
  2178.         call comnd              ; Get a confirm.
  2179.          jmp r
  2180.         mov extflg,1            ;  Set the exit flag.
  2181.         jmp rskp                ; Then return to system.
  2182. EXIT    ENDP
  2183.  
  2184.  
  2185. ; This is the 'help' command.  It gives a list of the commands.
  2186.  
  2187. HELP    PROC    NEAR
  2188.         mov ah,cmcfm
  2189.         call comnd              ; Get a confirm.
  2190.          jmp r
  2191.         mov ah,prstr            ; Print a string to the console.
  2192.         mov dx,offset tophlp    ; The address of the help message.
  2193.         int dos
  2194.         jmp rskp
  2195. HELP    ENDP
  2196.  
  2197.  
  2198. source  db      2048 DUP(?)     ; Buffer for data from port.
  2199. srcpnt  dw      0               ; Pointer in buffer (DI).
  2200. count   dw      0               ; Number of chars in int buffer.
  2201. savesi  dw      0               ; Save SI register here.        
  2202.  
  2203.  
  2204. ;       This is the CONNECT command.
  2205.  
  2206. TELNET  PROC    NEAR
  2207.         mov ah,cmcfm
  2208.         call comnd              ; Get a confirm.
  2209.          jmp r                  ;  Didn't get a confirm.
  2210.         mov ah,prstr            ; Output
  2211.         mov dx,offset crlf      ; a crlf.
  2212.         int dos
  2213.         mov dx,offset tmsg1
  2214.         int dos
  2215.         cld                     ; Do increment in string operations.
  2216.         cli                     ; Disable interrupts.
  2217.         xor ax,ax
  2218.         mov cx,ds               ; Save DS in CX.
  2219.         mov ds,ax               ; Use low core.
  2220.         mov bx,30H
  2221.         push [bx]               ; Serial Card Interrupt vector.
  2222.         mov bx,32H
  2223.         push [bx]
  2224.         mov bx,6CH              ; "break" interrupt vector.
  2225.         push [bx]
  2226.         mov bx,6EH
  2227.         push [bx]
  2228.         mov bx,30H
  2229.         mov ax,offset serint
  2230.         mov es,ax
  2231.         mov [bx],es             ; Setup int addr.
  2232.         mov bx,32H
  2233.         mov [bx],cs
  2234.         mov bx,6CH
  2235.         mov ax,offset intret
  2236.         mov es,ax
  2237.         mov [bx],es             ; ignore break int's (pt to "iret").
  2238.         mov bx,6EH
  2239.         mov [bx],cs
  2240.         mov ds,cx
  2241.         mov ssp,sp              ; Save SP to make an easy return.
  2242.         lea ax,cs:source
  2243.         mov cs:srcpnt,ax
  2244.         mov cs:savesi,ax        ; Source of data starts at buffer head.
  2245.         mov cs:count,0  
  2246.         mov di,cs:srcpnt        ; Address (for int) to put chars.
  2247.         mov ax,cs
  2248.         mov es,ax
  2249.         mov si,0                ; Place to get chars from.
  2250.         in al,21H               ; Set up 8259 interrupt controller.
  2251.         and al,0EFH             ; Enable INT4.
  2252.         out 21H,al
  2253.         mov dx,03FBH            ; Set up baud, parity, etc.
  2254.         mov al,3                ; (baud set independently)
  2255.         out dx,al
  2256.         mov dx,03F9H            ; Interrupt enable register.
  2257.         mov al,1
  2258.         out dx,al
  2259.         mov dl,0FCH             ; Enable int's from serial card.
  2260.         mov al,0BH
  2261.         out dx,al
  2262.         sti                     ; Enable interrupts.
  2263.         mov dl,0F8H
  2264.         in al,dx
  2265. telnoe: call plup               ; Char at port (type to console) ?
  2266.         cmp al,ESC
  2267.         jne telx
  2268.         jmp telesc
  2269. telx:   cmp al,DEL              ; Don't bother with deletes.
  2270.         je telnoe
  2271.         cmp al,XOFF             ; Skip all the following too.
  2272.         je telnoe
  2273.         cmp al,XON      
  2274.         je telnoe
  2275.         cmp al,00H              ; Null.
  2276.         je telnoe
  2277.         cmp al,BELL
  2278.         jne nobell
  2279.         call beep
  2280.         jmp telnoe
  2281. nobell: mov ah,14       
  2282.         mov bx,0
  2283.         int bios
  2284.         jmp telnoe
  2285. TELNET  ENDP
  2286.  
  2287.  
  2288. EXTLN   PROC    NEAR
  2289.         cli                     ; Disable interrupts.
  2290. ;       push ax
  2291.         mov dx,03FCH    
  2292.         mov al,3                ; Disable modem interrupts.
  2293.         out dx,al
  2294.         in al,21H               ; Interrupt control.
  2295.         or al,10H               ; Inhibit IRQ4.
  2296.         out 21H,al
  2297.         mov sp,ssp
  2298.         xor bx,bx
  2299.         mov cx,ds               ; Save DS register.
  2300.         mov ds,bx               ; Address low memory.
  2301. ;       pop ax
  2302.         mov bx,6EH
  2303.         pop [bx]
  2304.         mov bx,6CH
  2305.         pop [bx]
  2306.         mov bx,32H              ; Restore old interrupt vectors.
  2307.         pop [bx]
  2308.         mov bx,30H
  2309.         pop [bx]
  2310.         mov ds,cx               ; Restore DS.
  2311.         xor bx,bx
  2312.         sti
  2313.         mov ah,prstr
  2314.         mov dx,offset tmsg2
  2315.         int dos
  2316.         jmp rskp
  2317. EXTLN   ENDP
  2318.  
  2319. ; *********** serial port interrupt routine ********
  2320.  
  2321. SERINT  PROC  NEAR
  2322.         push dx
  2323.         push ax
  2324.         push es
  2325.         push di
  2326.         cld
  2327.         mov di,cs:srcpnt        ; Registers for storing data.
  2328.         mov ax,cs
  2329.         mov es,ax
  2330.         mov dx,03FDH            ; Asynch status port.
  2331.         in al,dx
  2332.         test al,1               ; Data available?
  2333.         jz retint               ; Nope.
  2334.         mov dl,0F8H
  2335.         in al,dx
  2336.         and al,7FH              ; Only want 7 bits.
  2337.         jz retint               ; Ignore nulls.
  2338.         cmp al,7FH              ; Ignore rubouts, too.
  2339.         jz retint
  2340.         stosb                   ; Store char in buffer.
  2341.         lea ax,cs:source
  2342.         sub di,ax
  2343.         and di,7FFH             ; Truncate buffer here.
  2344.         add di,ax
  2345.         inc cs:count
  2346. retint: mov cs:srcpnt,di
  2347.         sti
  2348.         mov al,64H
  2349.         out 20H,al              ;Send End-of-Interrupt to 8259.
  2350.         pop di
  2351.         pop es
  2352.         pop ax
  2353.         pop dx
  2354. intret: iret
  2355. SERINT  ENDP
  2356.  
  2357. PLUP    PROC    NEAR
  2358.         call prtchr
  2359.           ret                   ; Got a char.
  2360.           nop                   ; Use up three bytes.
  2361.           nop
  2362.         call conchr             ; See if char at cons (type to port).
  2363.           jmp extln             ; Go back to Kermit on micro.
  2364.         jmp plup 
  2365. PLUP    ENDP
  2366.  
  2367. ;************************System Dependent****************************
  2368.  
  2369. ;* These I/O routines are similar to those just above.
  2370.  
  2371. PRTCHR  PROC    NEAR
  2372.         cmp cs:count,0
  2373.         jnz prtch2
  2374.         jmp rskp                ; No data - check console.
  2375. prtch2: cli                     ; Disable int's.
  2376.         mov cx,ds
  2377.         mov ax,cs
  2378.         mov ds,ax
  2379.         mov si,cs:savesi
  2380.         lodsb                   ; Get char from buffer.
  2381.         lea dx,cs:source
  2382.         sub si,dx
  2383.         and si,7FFH             ; Truncate buffer after here.
  2384.         add si,dx
  2385.         dec cs:count
  2386.         mov cs:savesi,si 
  2387.         mov ds,cx
  2388.         sti                     ; Renable int's.
  2389.         ret
  2390. PRTCHR  ENDP
  2391.  
  2392.  
  2393. ; Generate a short beep.
  2394.  
  2395. BEEP    PROC    NEAR
  2396.         mov al,10110110B        ; Gen a short beep (long one losses data.)
  2397.         out timer+3,al          ; Code snarfed from Technical Reference.
  2398.         mov ax,533H
  2399.         out timer+2,al
  2400.         mov al,ah
  2401.         out timer+2,al
  2402.         in al,port_b
  2403.         mov ah,al
  2404.         or al,03
  2405.         out port_b,al
  2406.         sub cx,cx
  2407.         mov bl,1
  2408. beep0:  loop beep0
  2409.         dec bl          
  2410.         jnz beep0
  2411.         mov al,ah
  2412.         out port_b,al
  2413.         ret
  2414. BEEP    ENDP 
  2415.  
  2416. CONCHR  PROC    NEAR
  2417.         mov ah,1                ; Get keyboard status.
  2418.         int keyb
  2419.         jnz cnc0x       
  2420.         jmp rskp
  2421. cnc0x:  mov ah,0                ; Read a char.
  2422.         int keyb
  2423.         cmp al,0                ; Special char (cntrl-break)?
  2424.         jnz nobrk               ; Nope.
  2425.         cmp ah,3                ; 3 in ah means nul code.
  2426.         jz cnc1y                ; Skip nulls.
  2427.         cmp ah,0                ; Cntrl-Break?
  2428.         jne cnc1y
  2429.         xor cx,cx
  2430.         mov dx,03fbH
  2431.         in al,dx
  2432.         or al,40H               ; Set send-break bit
  2433.         out dx,al
  2434. pause:  loop pause
  2435.         xor al,40H
  2436.         out dx,al
  2437. cnc1y:  jmp rskp        
  2438.  
  2439. nobrk:  mov dl,al               ; Store char here.
  2440.         mov ah,escchr           ; Get the escape char.
  2441.         cmp ah,dl               ; Is it an escape char?
  2442.         jz intchr               ; If so go process it.
  2443.         cmp ibmflg,0
  2444.         je conch0
  2445.         or dl,080H              ; Turn on eighth bit.
  2446. conch0: push dx
  2447.         call prtout             ; Output the char to the port.
  2448.         pop dx
  2449.         mov ah,ecoflg           ; Get the echo flag.
  2450.         cmp ah,0                        ; Is it turned on?
  2451.         jnz cnc1x
  2452.         jmp rskp                 ; If not we're done here.
  2453. cnc1x:  and dl,7FH
  2454.         cmp dl,BS               ; Backspace?
  2455.         je cnc2x
  2456.         cmp dl,CR               ; Carriage return?
  2457.         je cnc2x
  2458.         cmp dl,BELL
  2459.         jne cnc2y
  2460.         call beep
  2461.         jmp rskp
  2462. cnc2y:  cmp dl,20H              ; Is it a control char?
  2463.         jge cnc2x       
  2464.         jmp rskp
  2465. cnc2x:  mov ah,dconio           ; Direct console output.
  2466.         int dos                 ; Echo the char.
  2467.         jmp rskp
  2468. CONCHR  ENDP
  2469.  
  2470. CONN    PROC    NEAR     
  2471. intchr: mov ah,dconio           ; Direct console I/O.
  2472.         mov dl,0FFH             ; Input.
  2473.         int dos                 ; Get a char.
  2474.         mov ah,al
  2475.         cmp ah,0                        ; Is the char a null?
  2476.         jz intchr               ; If so, go until we get a char.
  2477.         mov bh,ah               ; Save the actual char.
  2478.         and ah,137O             ; Convert to upper case.
  2479.         cmp ah,'C'                      ; Is it close?
  2480.         jne intch0
  2481.         ret
  2482. intch0: cmp ah,'S'                      ; Is it status?
  2483.         jnz inc0x
  2484.         jmp stat01               ; If so, jump to stat01 (it will return).
  2485. inc0x:  mov ah,bh                       ; Get the char.
  2486.         cmp ah,'?'                      ; Is it help?
  2487.         jne intch1              ; If not, go to the next check.
  2488.         mov dx,offset inthlp    ; If so, get the address of the help message.
  2489.         mov ah,prstr            ; Print it.
  2490.         int dos
  2491.         jmp intchr              ; Get another char.
  2492. intch1: mov ch,ah               ; Put the char into another reg.
  2493.         mov ah,escchr           ; Get the escape char.
  2494.         cmp ah,ch               ; Is it the escape char?
  2495.         jne intch2              ; If not, go send a beep to the user.
  2496.         cmp ibmflg,0
  2497.         je intc11
  2498.         or ch,080H              ; Turn on high order bit. 
  2499. intc11: mov dl,ch
  2500.         call prtout             ; Output it.
  2501.         jmp rskp                ; Return, we are done here.
  2502. intch2: mov dl,'G'-100O         ; Otherwise send a beep.
  2503.         mov ah,dconio
  2504.         int dos
  2505.         jmp rskp
  2506.  
  2507. ;* Another similar I/O routine.
  2508.  
  2509. ;************************System Dependent****************************
  2510.  
  2511. prtout: mov al,dl               ; Char must be in al.
  2512.         mov dx,03f8H
  2513.         out dx,al
  2514.         ret
  2515. CONN    ENDP
  2516. ;*
  2517.  
  2518. TELESC  PROC    NEAR
  2519.         cmp vtflg,0             ; Is vt52 flag on?
  2520.         jne vt0
  2521.         jmp telnoe              ; Don't do escape stuff if it's off.
  2522. vt0:    call plup
  2523.         mov ah,al                       ; Get the char.
  2524.         cmp ah,'Y'              ; Special char - move cursor.
  2525.         jne vt1
  2526.         jmp movcur
  2527. vt1:    cmp ah,'A'                      ; Less than an 'A'?
  2528.         jl vtig                 ; Yes - ignore.
  2529.         cmp ah,'M'+1            ; Greater than 'M'?
  2530.         jns vtig                ; Yes - ignore.
  2531.         mov al,'A'
  2532.         sub ah,al               ; Else make into index.
  2533.         shl ah,1
  2534.         mov bx,offset ttab      ; Load base addr of table.
  2535.         mov cl,ah               ; Move a into cx.
  2536.         mov ch,00H              ; Zero out high byte.
  2537.         add bx,cx               ; Double add index+offset.
  2538.         mov bx,[bx]             ; Get address of routine to call.
  2539.         jmp bx
  2540. vtig:                           ; Ignore escape sequence.
  2541.         push ax                 ; Push the char to be output.
  2542.         mov dl,esc              ; Load an escape.
  2543.         mov ah,conout           ; The function code
  2544.         int dos                 ; and the syscal.
  2545.         pop ax                  ; Restore the character
  2546.         mov dl,ah               ; and move to output register.
  2547.         mov ah,conout           ; The function
  2548.         int dos                 ; and the syscall.
  2549.         jmp telnoe              ; Return home.
  2550. TELESC  ENDP
  2551.  
  2552. TEL     PROC    NEAR
  2553. movcur: call plup
  2554.         sub al,32
  2555.         mov dh,al
  2556.         mov temp,dx             ; Save row position here.
  2557.         call plup
  2558.         mov dx,temp             ; Restore
  2559.         sub al,32               ; Comes with 37Q added on (& starts at 1).
  2560.         mov dl,al
  2561.         mov bh,0
  2562.         mov ah,2
  2563.         int bios
  2564.         jmp telnoe
  2565.  
  2566. curup:  mov ah,3                ; Cursor up function.
  2567.         mov bh,0
  2568.         int bios
  2569.         cmp dh,0
  2570.         je cup0
  2571.         sub dh,1
  2572.         mov ah,2
  2573.         int bios
  2574. cup0:   jmp telnoe
  2575.  
  2576. curdwn: mov ah,3                ; Cursor down.
  2577.         mov bh,0
  2578.         int bios
  2579.         cmp dh,24
  2580.         je cdn0
  2581.         add dh,1
  2582.         mov ah,2
  2583.         int bios
  2584. cdn0:   jmp telnoe
  2585.  
  2586. currt:  mov ah,3                ; Cursor right.
  2587.         mov bh,0
  2588.         int bios
  2589.         cmp dl,79
  2590.         je crt0
  2591.         add dl,1
  2592.         mov ah,2
  2593.         int bios
  2594. crt0:   jmp telnoe
  2595.  
  2596. curlft: mov ah,3                ; Cursor left.
  2597.         mov bh,0
  2598.         int bios
  2599.         cmp dl,0
  2600.         je clt0
  2601.         sub dl,1
  2602.         mov ah,2
  2603.         int bios
  2604. clt0:   jmp telnoe
  2605.  
  2606. curskp: jmp vtig                ; Ignore for now.
  2607.  
  2608. curhm:  call locate
  2609.         jmp telnoe
  2610.  
  2611. curscr: mov ah,3                ; Clear to end of screen.
  2612.         mov bh,0
  2613.         int bios
  2614.         cmp dx,0
  2615.         jne csr0
  2616.         call cmblnk
  2617.         jmp telnoe
  2618. csr0:   cmp dl,0
  2619.         je csr1
  2620.         push dx
  2621.         call curln
  2622.         pop dx
  2623.         add dh,1
  2624.         mov dl,0
  2625. csr1:   mov cx,dx
  2626.         mov dx,184FH
  2627.         mov bh,7
  2628. ;       mov al,25
  2629. ;       sub al,ch
  2630.         mov al,0
  2631.         mov ah,7
  2632.         int bios
  2633.         jmp telnoe
  2634.  
  2635. curln:  mov ah,3                ; Clear to end of line.
  2636.         mov bh,0
  2637.         int bios                ; Get current cursor position
  2638.         mov cx,dx
  2639.         mov dl,79
  2640.         mov ah,7
  2641.         mov al,0
  2642.         mov bh,7
  2643.         int bios
  2644.         jmp telnoe
  2645.  
  2646. inslin: mov ah,3                ; Get cursor position.
  2647.         mov bh,0
  2648.         int bios
  2649.         mov temp,dx             ; Save here.
  2650.         mov cx,dx
  2651.         mov cl,0                ; Start at beginning of row.
  2652.         mov dx,184FH            ; End at lower corner of screen.
  2653.         mov ax,0701H
  2654.         mov bh,7
  2655.         int bios                ; Scroll down one line.
  2656.         mov dx,temp             ; Get back where we were.
  2657.         mov dl,0
  2658.         mov ah,2
  2659.         mov bh,0
  2660.         int bios
  2661.         jmp telnoe
  2662.  
  2663. dellin: mov ah,3
  2664.         mov bh,0
  2665.         int bios                ; Get current cursor position. 
  2666.         mov temp,dx             ; Remember the place.
  2667.         mov ax,0601H            ; Scroll up one line.
  2668.         mov cx,dx
  2669.         mov cl,0                ; Start at beginning of row.
  2670.         mov dx,184FH
  2671.         mov bh,7
  2672.         int bios
  2673.         mov dx,temp
  2674.         mov dl,0
  2675.         mov ah,2
  2676.         mov bh,0
  2677.         int bios
  2678.         jmp telnoe
  2679.         
  2680. TEL     ENDP
  2681.  
  2682. ;*
  2683.  
  2684. ; This is the SET command.
  2685.  
  2686. SETCOM  PROC    NEAR
  2687.         mov dx,offset settab    ; Parse a keyword from the set table.
  2688.         mov bx,offset sethlp
  2689.         mov ah,cmkey
  2690.         call comnd
  2691.          jmp r
  2692.         call bx
  2693.         jmp rskp
  2694. SETCOM  ENDP
  2695.  
  2696.  
  2697. ;       This is the ESCAPE character SET subcommand.
  2698.  
  2699. ESCAPE  PROC    NEAR
  2700.  
  2701.         call cmgtch             ; Get a char.
  2702.         jns es1                 ; Terminator or no?
  2703.         and ah,7FH              ; Turn off minus bit.
  2704.         cmp ah,'?'
  2705.         jne es0
  2706. esch:   mov dx,offset eschlp
  2707.         mov ah,prstr
  2708.         int dos
  2709.         mov dx,offset crlf
  2710.         int dos
  2711.         mov dx,offset kerm
  2712.         int dos
  2713.         mov bx,cmdptr
  2714.         mov al,'$'
  2715.         mov [bx],al
  2716.         mov dx,offset cmdbuf
  2717.         int dos
  2718.         jmp repars
  2719. es0:    mov dx,offset escmes    ; Print a message.
  2720.         mov ah,prstr
  2721.         int dos
  2722.         mov ah,conin
  2723.         int dos                 ; Get new escape char.
  2724.         mov ah,al
  2725.         cmp ah,'?'
  2726.         je esch
  2727.         cmp ah,cr
  2728.         jne es1
  2729.         mov ah,prstr
  2730.         mov dx,offset ermes3
  2731.         int dos
  2732.         ret
  2733. es1:    mov escchr,ah           ; Save new value.
  2734.         ret
  2735. ESCAPE  ENDP
  2736.  
  2737.  
  2738. ;       This is the LOCAL echo SET subcommand.
  2739.  
  2740. LCAL    PROC    NEAR
  2741.         mov dx,offset ontab
  2742.         mov bx,offset onhlp
  2743.         mov ah,cmkey
  2744.         call comnd
  2745.          jmp r
  2746.         push bx                 ; Save the parsed value.
  2747.         mov ah,cmcfm
  2748.         call comnd              ; Get a confirm.
  2749.          jmp r                  ;  Didn't get a confirm.
  2750.         pop bx
  2751.         mov ecoflg,bl           ; Set the local echo flag.
  2752.         ret
  2753. LCAL    ENDP
  2754.  
  2755. ;       This is the VT52 emulation SET subcommand.
  2756.  
  2757. VT52EM  PROC    NEAR
  2758.         mov dx,offset ontab
  2759.         mov bx,offset onhlp
  2760.         mov ah,cmkey
  2761.         call comnd
  2762.          jmp r
  2763.         push bx
  2764.         mov ah,cmcfm
  2765.         call comnd              ; Get a confirm.
  2766.          jmp r                  ;  Didn't get a confirm.
  2767.         pop bx
  2768.         mov vtflg,bl            ; Set the VT52 emulation flag.
  2769.         ret
  2770. VT52EM  ENDP
  2771.  
  2772. ;       This is the SET IBM command.
  2773.  
  2774. IBMSET  PROC    NEAR
  2775.         mov dx,offset ontab
  2776.         mov bx,offset onhlp
  2777.         mov ah,cmkey
  2778.         call comnd
  2779.          jmp r
  2780.         push bx
  2781.         mov ah,cmcfm
  2782.         call comnd              ; Get a confirm.
  2783.          jmp r                  ;  Didn't get a confirm.
  2784.         pop bx
  2785.         mov ibmflg,bl           ; Set the IBM flag.
  2786.         ret
  2787. IBMSET  ENDP
  2788.  
  2789. ;       This is the SET File-Warning command.
  2790.  
  2791. FILWAR  PROC    NEAR
  2792.         mov dx,offset ontab
  2793.         mov bx,offset onhlp
  2794.         mov ah,cmkey
  2795.         call comnd
  2796.          jmp r
  2797.         push bx
  2798.         mov ah,cmcfm
  2799.         call comnd              ; Get a confirm.
  2800.          jmp r                  ;  Didn't get a confirm.
  2801.         pop bx
  2802.         mov flwflg,bl           ; Set the IBM flag.
  2803.         ret
  2804. FILWAR  ENDP
  2805.  
  2806. ; Sets debugging mode on and off.
  2807.  
  2808. DEBST   PROC    NEAR
  2809.         mov dx,offset ontab
  2810.         mov bx,offset onhlp
  2811.         mov ah,cmkey
  2812.         call comnd
  2813.          jmp r
  2814.         push bx
  2815.         mov ah,cmcfm
  2816.         call comnd              ; Get a confirm.
  2817.          jmp r                  ;  Didn't get a confirm.
  2818.         pop bx
  2819.         mov debug,bl           ; Set the IBM flag.
  2820.         ret
  2821. DEBST   ENDP
  2822.  
  2823. ;  This function sets the baud rate.
  2824.  
  2825. BAUDST  PROC    NEAR
  2826.         mov dx,offset bdtab
  2827.         mov bx,offset bdhlp
  2828.         mov ah,cmkey
  2829.         call comnd
  2830.          jmp r
  2831.         push bx
  2832.         mov ah,cmcfm
  2833.         call comnd              ; Get a confirm.
  2834.          jmp r                  ; Didn't get one.
  2835.         pop bx
  2836.         mov baud,bx           ; Set the IBM flag.
  2837.         mov dx,03FBH            ; LCR
  2838.         in al,dx
  2839.         mov bl,al
  2840.         or ax,80H
  2841.         out dx,al
  2842.         mov dx,03F8H
  2843.         mov ax,baud
  2844.         out dx,al
  2845.         inc dx
  2846.         mov al,ah
  2847.         out dx,al
  2848.         mov dx,03FBH
  2849.         mov al,bl
  2850.         out dx,al
  2851.         ret
  2852. BAUDST  ENDP
  2853.  
  2854. ;       This is the STATUS command.
  2855.  
  2856. STATUS  PROC    NEAR
  2857.         call stat0
  2858.          jmp r
  2859.         jmp rskp
  2860. STATUS  ENDP
  2861.  
  2862. STAT0   PROC    NEAR
  2863.         mov ah,cmcfm
  2864.         call comnd              ; Get a confirm.
  2865.          jmp r                  ;  Didn't get a confirm.
  2866. stat01: mov dx,offset locst     ; Assume local echo on.
  2867.         cmp ecoflg,0            ; Is the local echo flag on?
  2868.         jnz stat1               
  2869.         mov dx,offset remst     ; If not say so.
  2870. stat1:  mov ah,prstr            ; Print it.
  2871.         int dos
  2872.         mov dx,offset vtemst    ; Get address of the VT52 emulation string.
  2873.         cmp vtflg,0             ; Is the VT52 emulation flag on?
  2874.         jnz stat2
  2875.         mov dx,offset novtst    ; If not say so.
  2876. stat2:  mov ah,prstr            ; Print it.
  2877.         int dos
  2878.         mov dx,offset ibmst     ; Is IBM flag on?
  2879.         cmp ibmflg,0
  2880.         jnz stat3
  2881.         mov dx,offset noibm     ; Say it's not.
  2882. stat3:  mov ah,prstr
  2883.         int dos
  2884.         mov dx,offset deboff    ; Assume debug mode is off.
  2885.         cmp debug,0
  2886.         je stat4
  2887.         mov dx,offset debon
  2888. stat4:  mov ah,prstr
  2889.         int dos
  2890.         mov dx,offset flwon     ; Assume file-warning on.
  2891.         cmp flwflg,0
  2892.         jne stat5
  2893.         mov dx,offset flwoff
  2894. stat5:  mov ah,prstr
  2895.         int dos
  2896.         mov dx,offset b48st     ; Assume 4800 baud.
  2897.         cmp baud,B4800
  2898.         jz stat9
  2899.         mov dx,offset b12st
  2900.         cmp baud,B1200
  2901.         jz stat9
  2902.         mov dx,offset b18st
  2903.         cmp baud,B1800
  2904.         jz stat9
  2905.         mov dx,offset b24st
  2906.         cmp baud,B2400
  2907.         jz stat9
  2908.         mov dx,offset b96st
  2909.         cmp baud,B9600
  2910.         jz stat9
  2911.         mov dx,offset b03st
  2912. stat9:  mov ah,prstr
  2913.         int dos
  2914.         mov dx,offset cmcrlf    ; Get the address of a crlf.
  2915.         mov ah,prstr            ; Print it.
  2916.         int dos
  2917.         jmp rskp
  2918. STAT0   ENDP
  2919.  
  2920.  
  2921.  
  2922. ;       Utility routines
  2923.  
  2924. ; Jumping to this location is like retskp.  It assumes the instruction
  2925. ;   after the call is a jmp addr.
  2926.  
  2927. RSKP    PROC    NEAR
  2928.         pop bp
  2929.         add bp,3
  2930.         push bp
  2931.         ret
  2932. RSKP    ENDP
  2933.  
  2934. ; Jumping here is the same as a ret.
  2935.  
  2936. R       PROC    NEAR
  2937.         ret
  2938. R       ENDP
  2939.  
  2940. ; This routine prints the number in AX on the screen.
  2941. ;       (Thanks to Jeff Damens)
  2942.  
  2943. NOUT    PROC    NEAR
  2944.         push bx                 ; Save some stuff.
  2945.         push cx
  2946.         push dx
  2947.         push ax
  2948.         mov bh,0                ; Don't print leading zeros.
  2949.         and ah,0F0H             ; Only want high order nibble.
  2950.         mov cl,4
  2951.         shr ah,cl
  2952.         call pdig               ; Print the digit.
  2953.         pop ax                  ; Restore argument.
  2954.         and ah,0FH              ; Just the low order nibble.
  2955.         call pdig
  2956.         mov ah,al
  2957.         and ah,0F0H             ; Only want high order nibble.
  2958.         mov cl,4
  2959.         shr ah,cl
  2960.         call pdig               ; Print the digit.
  2961.         mov ah,al
  2962.         and ah,0FH              ; Just the low order nibble.
  2963.         mov bh,0FFH             ; Make sure at least one zero is printed.
  2964.         call pdig
  2965.         pop dx                  ; Restore some stuff.
  2966.         pop cx
  2967.         pop bx
  2968.         ret
  2969. NOUT    ENDP
  2970.  
  2971.         ; print the digit in register AH
  2972.  
  2973. PDIG    PROC    NEAR
  2974.         push ax                 ; Save it.
  2975.         cmp ah,0
  2976.         jne pdig2
  2977.         cmp bh,0
  2978.         jne pdig2
  2979.         pop ax
  2980.         ret
  2981. pdig2:  mov bh,0FFH             ; Set the print zero flag.
  2982.         cmp ah,10               ; Do we use digits or a-f?
  2983.         jl usedig               ; Digit.
  2984.         add ah,'A'-10           ; Compute digit
  2985.         jmp havdig              ; and proceed.
  2986. usedig: add ah,'0'              ; Convert to digit
  2987. havdig: mov dl,ah
  2988.         mov ah,conout
  2989.         int dos
  2990.         pop ax
  2991.         ret
  2992. PDIG    ENDP
  2993.  
  2994.  
  2995. ;       This set of routines provides a user oriented way of parsing
  2996. ;       commands.  It is similar to that of the COMND JSYS in TOPS-20.
  2997.  
  2998.  
  2999. ;       This routine prints the prompt in DE and specifies the reparse
  3000. ;       address.
  3001.  
  3002. PROMPT  PROC  NEAR
  3003.         pop bx                  ; Get the return address.
  3004.         push bx                 ; Put it on the stack again.
  3005.         mov cmrprs,bx           ; Save as addr to go to on reparse.
  3006.         mov bx,0                        ; Clear out register.
  3007.         add bx,sp               ; Get the present stack pointer.
  3008.         mov cmostp,bx           ; Save for later restoral.
  3009.         mov cmprmp,dx           ; Save pointer to the prompt.
  3010.         mov bx,offset cmdbuf
  3011.         mov cmcptr,bx           ; Initialize the command pointer.
  3012.         mov cmdptr,bx
  3013.         mov ah,0
  3014.         mov cmaflg,ah           ; Zero the flags.
  3015.         mov cmccnt,ah
  3016.         mov cmsflg,0FFH
  3017.         mov ah,prstr
  3018.         mov dx,offset cmcrlf
  3019.         int dos
  3020.         mov ah,prstr            ; Print the prompt.
  3021.         mov dx,cmprmp
  3022.         int dos
  3023.         ret
  3024. PROMPT  ENDP
  3025.  
  3026. ;       This address is jumped to on reparse.
  3027.  
  3028. PARSE   PROC NEAR 
  3029. repars: mov sp,cmostp           ; new sp <-- old sp
  3030.         mov bx,offset cmdbuf
  3031.         mov cmdptr,bx
  3032.         mov ah,0FFH
  3033.         mov cmsflg,ah
  3034.         mov bx,cmrprs           ; Get the reparse address.
  3035.         call bx                 ; Go there.
  3036.  
  3037. ;       This address can be jumped to on a parsing error.
  3038.  
  3039. prserr: mov sp,cmostp           ; Set new sp to old one.
  3040.         mov bx,offset cmdbuf
  3041.         mov cmcptr,bx           ; Initialize the command pointer.
  3042.         mov cmdptr,bx
  3043.         mov ah,0
  3044.         mov cmaflg,ah           ; Zero the flags.
  3045.         mov cmccnt,ah
  3046.         mov cmsflg,0FFH
  3047.         mov ah,prstr
  3048.         mov dx,offset cmcrlf
  3049.         int dos
  3050.         mov ah,prstr            ; Print the prompt.
  3051.         mov dx,cmprmp           ; Get the prompt.
  3052.         int dos
  3053. ;* Instead return to before the prompt call.
  3054.         mov bx,cmrprs
  3055.         call bx
  3056. PARSE   ENDP
  3057.  
  3058. ;       This routine parses the specified function in AH. Any additional
  3059. ;       information is in DX and BX.
  3060. ;       Returns +1 on success
  3061. ;               +4 on failure (assumes a JMP follows the call)
  3062.  
  3063. CMND    PROC NEAR
  3064. comnd:  mov cmstat,ah           ; Save what we are presently parsing.
  3065.         call cminbf             ; Get chars until an action or a erase char.
  3066.         mov ah,cmstat           ; Restore 'ah' for upcoming checks.
  3067.         cmp ah,cmcfm            ; Parse a confirm?
  3068.         jz cmcfrm               ; Go get one.
  3069.         cmp ah,cmkey            ; Parse a keyword?
  3070.         jnz cm1
  3071.         jmp cmkeyw               ; Try and get one.
  3072. cm1:    cmp ah,cmifi            ; Parse an input file spec?
  3073.         jnz cm2
  3074.         jmp cmifil              ; Go get one.
  3075. cm2:    cmp ah,cmofi            ; Output file spec?
  3076.         jnz cm3
  3077.         jmp cmofil              ; Go get one.
  3078. cm3:    mov ah,prstr            ; Else give error.
  3079.         mov dx,offset cmer00    ; "?Unrecognized COMND call"
  3080.         int dos
  3081.         ret
  3082.  
  3083. ; This routine gets a confirm.
  3084.  
  3085. cmcfrm: call cmgtch             ; Get a char.
  3086.         cmp ah,0                ; Is it negative (a terminator; a space or
  3087.                                 ; a tab will not be returned here as they
  3088.                                 ; will be seen as leading white space.)
  3089.         js cmcfr0
  3090.         ret                     ; If not, return failure.
  3091. cmcfr0: and ah,7FH                      ; Turn off the minus bit.
  3092.         cmp ah,esc                      ; Is it an escape?
  3093.         jne cmcfr2
  3094.         mov ah,conout
  3095.         mov dl,bell             ; Get a bell.
  3096.         int dos
  3097.         mov ah,0
  3098.         mov cmaflg,ah           ; Turn off the action flag.
  3099.         mov bx,cmcptr           ; Move the pointer to before thee scape.
  3100.         dec bx
  3101.         mov cmcptr,bx
  3102.         mov cmdptr,bx
  3103.         dec cmccnt              ; Decremrnt the char count.
  3104.         jmp cmcfrm              ; Try again.
  3105. cmcfr2: cmp ah,'?'                      ; Curious?
  3106.         jne cmcfr3
  3107.         mov ah,prstr            ; Print something useful.
  3108.         mov dx,offset cmin00
  3109.         int dos
  3110.         mov ah,prstr
  3111.         mov dx,offset cmcrlf            ; Print a crlf.
  3112.         int dos
  3113.         mov ah,prstr
  3114.         mov dx,cmprmp           ; Reprint the prompt.
  3115.         int dos
  3116.         mov bx,cmdptr           ; Get the pointer into the buffer.
  3117.         mov ah,'$'              ; Put a $ there for printing.
  3118.         mov [bx],ah
  3119.         mov bx,cmcptr
  3120.         dec bx                  ; Decrement & save the buffer pointer.
  3121.         mov  cmcptr,bx
  3122.         mov ah,prstr
  3123.         mov dx,offset cmdbuf
  3124.         int dos
  3125.         mov ah,0                        ; Turn off the action flag.
  3126.         mov cmaflg,ah
  3127.         jmp repars              ; Reparse everything.
  3128.  
  3129. cmcfr3: cmp ah,ff                       ; Is it a form feed?
  3130.         jne cmcfr4
  3131.         call cmblnk             ; If so blank the screen.
  3132. cmcfr4: jmp rskp
  3133.  
  3134. ;       This routine parses a keyword from the table pointed
  3135. ;       to in DX.  The format of the table is as follows:
  3136. ;
  3137. ;       addr:   db      n       ; Where n is the # of entries in the table.
  3138. ;               db      m       ; M is the size of the keyword.
  3139. ;               db      'string$' ; Where string is the keyword.
  3140. ;               dw      ab      ; Where ab is data to be returned.
  3141. ;
  3142. ;       The keywords must be in alphabetical order.
  3143.  
  3144.  
  3145. cmkeyw: mov cmhlp,bx            ; Save the help.
  3146.         mov cmptab,dx           ; Save the beginning of keyword table.
  3147.         mov bx,dx
  3148.         mov ch,[bx]                     ; Get number of entries in table.
  3149.         inc bx
  3150.         mov dx,cmdptr           ; Save command pointer.
  3151.         mov cmsptr,dx           ; Save pointer's here.
  3152. cmky1:  cmp ch,0                ; Any commands left to check?
  3153.         jne cmky2
  3154.         ret                     ; Fail if not.
  3155. cmky2:  dec ch
  3156.         mov cl,0                ; Keep track of how many chars read in so far.
  3157.         call cmgtch             ; Get a char.
  3158.         cmp ah,0                ; Do we have a terminator?
  3159.         jns cmky2x 
  3160.         jmp cmky4               ; Negative number means we do.
  3161. cmky2x: inc bx                  ; Point to first letter of keyword.
  3162.         inc cl                  ; Read in another char.
  3163.         mov al,[bx]                   
  3164.         cmp ah,'a'              ; Less than a?
  3165.         jl cmky21               ; If so, don't capitalize.
  3166.         cmp ah,'z'+1            ; More than z?
  3167.         jns cmky21
  3168.         and ah,137O             ; Capitalize the letter.
  3169. cmky21: cmp ah,al
  3170.         je cmky3
  3171.         jg cmky2y
  3172.         jmp cmky41              ; Fail if ah preceeds al alphabetically.
  3173. cmky2y: jmp cmky6               ; Not this keyword - try the next.
  3174. cmky3:  inc bx                  ; We match here, how 'bout next char?
  3175.         mov al,[bx]
  3176.         cmp al,'$'               ; End of keyword?
  3177.         jne cmky3x
  3178.         jmp cmky7                ; Succeed.
  3179. cmky3x: mov dl,al               ; Save al's char here.
  3180.         call cmgtch
  3181.         inc cl                  ; Read in another char.
  3182.         mov al,dl
  3183.         cmp ah,'a'
  3184.         jl cmky31
  3185.         cmp ah,'z'+1
  3186.         jns cmky31
  3187.         and ah,137O
  3188. cmky31: cmp ah,9BH              ; Escape Recognition (escape w/minus bit on)?
  3189.         je cmky3y
  3190.         cmp ah,0A0H             ; A space?
  3191.         je cmky3y
  3192.         cmp ah,8DH              ; Carriage return?
  3193.         je cmky3y
  3194.         jmp cmky38
  3195. cmky3y: mov cmkptr,bx           ; Save bx here.
  3196.         mov cmsiz,cx            ; Save size info.
  3197.         mov cmchr,ah            ; Save char for latter.
  3198.         call cmambg             ; See if input is ambiguous or not.
  3199.          jmp cmky32             ; Succeeded (not ambiguous).
  3200.         mov ah,cmchr
  3201.         cmp ah,9BH              ; Escape?
  3202.         je cmky3z
  3203.         jmp cmky41              ; Fail.
  3204. cmky3z: mov ah,conout           ; Else, ring a bell.
  3205.         mov dl,bell
  3206.         int dos
  3207.         mov bx,cmcptr           ; Move pointer to before the escape.
  3208.         dec bx
  3209.         mov cmcptr,bx
  3210.         mov cmdptr,bx
  3211.         dec cmccnt              ; Decrement char count.
  3212.         mov bx,cmkptr           ; Failed - pretend user never typed ....
  3213.         mov cx,cmsiz            ; ... in a char.
  3214.         dec cl                  ; Don't count the escape.
  3215.         dec bx
  3216.         mov cmaflg,0            ; Reset the action flag.
  3217.         jmp cmky3               ; Keep checking.
  3218. cmky32: mov cx,cmsiz            ; Restore info.
  3219.         mov bx,cmkptr           ; Our place in the keyword table.
  3220.         cmp cmchr,0A0H          ; Space?
  3221.         je cmky35
  3222.         cmp cmchr,8DH           ; Carriage return?
  3223.         je cmky35
  3224.         dec cmcptr              ; Pointer into buffer of input.
  3225.         mov dx,cmcptr
  3226. cmky33: mov ah,[bx]             ; Get next char in keyword.
  3227.         cmp ah,'$'              ; Are we done yet?
  3228.         jz cmky34
  3229.         mov di,dx
  3230.         mov [di],ah
  3231.         inc bx
  3232.         inc dx
  3233.         inc cmccnt
  3234.         jmp cmky33
  3235. cmky34: mov ah,' '
  3236.         mov di,dx
  3237.         mov [di],ah             ; Put a blank in the buffer.
  3238.         inc dx
  3239.         mov cx,cmcptr           ; Remember where we were (for printing below).
  3240.         mov cmcptr,dx           ; Update our pointers.
  3241.         mov cmdptr,dx
  3242.         mov ah,'$'
  3243.         mov di,dx
  3244.         mov [di],ah             ; Add '$' for printing.
  3245.         mov ah,prstr
  3246.         mov dx,cx               ; Point to beginning of filled in data.
  3247.         int dos
  3248.         inc bx                  ; Point to address we'll need.
  3249.         mov bx,[bx]
  3250.         mov cmaflg,0            ; Turn off action flag.
  3251.         jmp rskp
  3252.  
  3253. cmky35: inc bx
  3254.         mov ah,[bx]             ; Find end of keyword. 
  3255.         cmp ah,'$'
  3256.         jne cmky35      
  3257.         inc bx
  3258.         mov bx,[bx]             ; Address of next routine to call.
  3259. ;       mov cmaflg,0            ; Zero the action flag.
  3260.         jmp rskp
  3261.  
  3262. cmky38: cmp ah,al
  3263.         jne cmky6               ; Go to end of keyword and try next.
  3264.         jmp cmky3
  3265.            
  3266. cmky4:  and ah,7FH              ; Turn off minus bit.
  3267.         cmp ah,'?'              ; Need help?
  3268.         je cmky5
  3269.         cmp ah,' '              ; Just a space - no error.
  3270.         je cmky51
  3271.         cmp ah,cr
  3272.         je cmky51
  3273.         cmp ah,tab
  3274.         je cmky51 
  3275.         cmp ah,esc              ; Ignore escape?
  3276.         je cmky43
  3277. cmky41: mov ah,prstr
  3278.         mov dx,offset cmer03
  3279.         int dos
  3280.         jmp prserr              ; Parse error - give up.
  3281.  
  3282. cmky43: mov ah,conout           ; Ring a bell.
  3283.         mov dl,bell
  3284.         int dos
  3285.         mov bx,cmcptr
  3286.         dec bx
  3287.         mov cmcptr,bx
  3288.         mov cmdptr,bx
  3289.         dec cmccnt              ; Don't count the escape.
  3290.         mov cmaflg,0            ; Reset action flag.
  3291.         inc ch                  ; Account for a previous 'dec'.
  3292.         jmp cmky1               ; Start over.
  3293.  
  3294. cmky5:  mov ah,prstr
  3295.         mov dx,cmhlp            ; Print the help text.
  3296.         int dos
  3297.         mov dx,offset crlf
  3298.         int dos
  3299.         mov dx,offset kerm
  3300.         int dos
  3301.         mov bx,cmdptr           ; Get pointer into buffer.
  3302.         mov al,'$'
  3303.         mov [bx],al             ; Add dollar sign for printing.
  3304.         mov dx,offset cmdbuf
  3305.         int dos
  3306.         dec cmcptr              ; Don't keep it in the buffer.
  3307.         dec cmccnt              ; Don't conut it.
  3308.         mov cmaflg,0            ; Turn off the action flag.
  3309.         jmp repars
  3310.  
  3311. cmky51: jmp prserr
  3312.  
  3313. cmky6:  inc bx                  ; Find end of keyword.
  3314.         mov al,[bx]
  3315.         cmp al,'$'
  3316.         jne cmky6             
  3317.         inc bx                  ; Beginning of next command.
  3318.         inc bx
  3319.         inc bx
  3320.         mov dx,cmsptr           ; Get old cmdptr.
  3321.         mov cmdptr,dx           ; Restore.
  3322.         mov cmsflg,0FFH
  3323.         jmp cmky1               ; Keep trying.
  3324.  
  3325. cmky7:  call cmgtch             ; Get char.
  3326.         cmp ah,0
  3327.         js cmky71               ; Ok if a terminator.
  3328.         dec bx
  3329.         jmp cmky6               ; No match - try next keyword.
  3330. cmky71: inc bx                  ; Get necessary data.
  3331.         mov bx,[bx]
  3332.         cmp ah,9BH              ; An escape?
  3333.         jne cmky72
  3334.         mov ah,prstr
  3335.         mov dx,offset prsp      ; Print a space.
  3336.         int dos
  3337.         mov di,cmcptr
  3338.         dec di
  3339.         mov ah,20H
  3340.         mov [di],ah             ; Replace escape char with space.
  3341.         mov cmaflg,0
  3342.         mov cmsflg,0FFH         ; Pretend they typed a space.
  3343. cmky72: jmp rskp
  3344.  
  3345. ; See if keyword is unambiguous or not from what the user has typed in.
  3346.  
  3347. cmambg: cmp ch,0                ; Any keywords left to check?
  3348.         jne cmamb0
  3349.         ret                     ; If not then not ambiguous.
  3350. cmamb0: inc bx                  ; Go to end of keyword ...
  3351.         mov al,[bx]             ; So we can check the next one.
  3352.         cmp al,'$'
  3353.         jne cmamb0
  3354.         add bx,4                ; Point to start of next keyword.
  3355.         dec cl                  ; Don't count escape.
  3356.         mov dx,cmsptr           ; Buffer with input typed by user.
  3357. cmamb1: mov ah,[bx]             ; Keyword char. 
  3358.         mov di,dx
  3359.         mov al,[di]             ; Input char.
  3360.         cmp al,'a'              ; Do capitalizing.
  3361.         jl cmam11
  3362.         cmp al,'z'+1
  3363.         jns cmam11
  3364.         and al,137O
  3365. cmam11: cmp ah,al               ; Keyword bigger than input (alphabetically)?
  3366.         jle cmamb2              ; No - keep checking.
  3367.         ret                     ; Yes - not ambiguous.
  3368. cmamb2: inc bx                  ; Advance one char.
  3369.         inc dx
  3370.         dec cl
  3371.         jnz cmamb1
  3372.         jmp rskp                ; Fail - it's ambiguous.
  3373.  
  3374. cmifil: mov bx,dx               ; Get the fcb address in bx.
  3375.         mov cmfcb,bx            ; Save it.
  3376.         mov ch,0                ; Initialize char count.
  3377.         mov ah,0
  3378.         mov [bx],ah                     ; Set the drive to default to current.
  3379.         inc bx
  3380.         mov cmfcb2,bx
  3381.         mov cl,' '
  3382. cmifi0: mov [bx],cl                     ; Blank the FCB.
  3383.         inc bx
  3384.         inc ah
  3385.         cmp ah,0BH                      ; Twelve?
  3386.         jl cmifi0
  3387. cmifi1: call cmgtch             ; Get another char.
  3388.         cmp ah,0                        ; Is it an action character.
  3389.         jns cmifi2
  3390.         and ah,7FH                      ; Turn off the action bit.
  3391.         cmp ah,'?'                      ; A question mark?
  3392.         jne cmif12
  3393.         mov al,0
  3394.         mov cmaflg,al           ; Blank the action flag.
  3395.         dec cmcptr           ; Decrement the buffer pointer.
  3396.         dec cmccnt              ; Decrement count.
  3397. ;        jmp cmifi8              ; Treat like any other character.
  3398.         mov ah,prstr
  3399.         mov dx,offset filhlp    ; Help  message.
  3400.         int dos
  3401.         mov dx,offset crlf
  3402.         int dos
  3403.         mov dx,offset kerm
  3404.         int dos
  3405.         mov bx,cmdptr
  3406.         mov al,'$'
  3407.         mov [bx],al             ; Put in dollar sign for printing.
  3408.         mov dx,offset cmdbuf
  3409.         int dos
  3410.         jmp repars
  3411. cmif12: cmp ah,esc                      ; An escape?
  3412.         jne cmif13
  3413.         mov ah,0
  3414.         mov cmaflg,ah           ; Turn off the action flag.
  3415.         mov ah,conout
  3416.         mov dl,bell
  3417.         int dos         ; Ring the bell.
  3418.         mov bx,cmcptr           ; Move the pointer to before the escape.
  3419.         dec bx
  3420.         mov cmcptr,bx
  3421.         mov cmdptr,bx
  3422.         dec cmccnt              ; Decrement char count.
  3423.         jmp repars
  3424. cmif13: mov ah,ch                       ; It must be a terminator.
  3425.         cmp ah,0                        ; Test the length of the file name.
  3426.         jnz cmf3x
  3427.         jmp cmifi9               ; If zero complain.
  3428. cmf3x:  cmp ah,0DH
  3429.         js cmf3y
  3430.         jmp cmifi9              ; If too long complain.
  3431. cmf3y:  jmp rskp                ; Otherwise we have succeeded.
  3432. cmifi2: cmp ah,'.'
  3433.         jne cmifi3
  3434.         inc ch
  3435.         mov ah,ch
  3436.         cmp ah,1H                       ; Any chars yet?
  3437.         jnz cmf2x
  3438.         jmp cmifi9               ; No, give error.
  3439. cmf2x:  cmp ah,0AH                      ; Tenth char?
  3440.         js cmf2y
  3441.         jmp cmifi9              ; Past it, give an error.
  3442. cmf2y:  mov dl,9H
  3443.         mov dh,0
  3444.         mov bx,cmfcb
  3445.         add bx,dx               ; Point to file type field.
  3446.         mov cmfcb2,bx
  3447.         mov ch,9H               ; Say we've gotten nine.
  3448.         jmp cmifi1              ; Get the next char.
  3449. cmifi3: cmp ah,':'
  3450.         jne cmifi4
  3451.         inc ch
  3452.         cmp ch,2H                       ; Is it in right place for a drive?
  3453.         jne cmifi9              ; If not, complain.
  3454.         mov bx,cmfcb2
  3455.         sub bx,1
  3456.         mov ah,[bx]                     ; Get the drive name.
  3457.         sub ah,'@'              ; Get the drive number.
  3458.         mov cmfcb2,bx
  3459.         mov bx,cmfcb
  3460.         mov [bx],ah                     ; Put it in the fcb.
  3461.         jmp cmifi1
  3462. cmifi4: cmp ah,'*'
  3463.         jne cmifi7
  3464.         mov ah,ch
  3465.         cmp ah,8H                       ; Is this in the name or type field?
  3466.         jz cmifi9               ; If its where the dot should be give up.
  3467.         jns cmifi5              ; Type.
  3468.         mov cl,8H               ; Eight chars.
  3469.         jmp cmifi6
  3470. cmifi5: mov cl,0CH              ; Three chars.
  3471. cmifi6: mov bx,cmfcb2           ; Get a pointer into the FCB.
  3472.         mov ah,'?'
  3473.         mov [bx],ah                     ; Put a question mark in.
  3474.         inc bx
  3475.         mov cmfcb2,bx
  3476.         inc ch
  3477.         mov ah,ch
  3478.         cmp ah,cl
  3479.         jl cmifi6               ; Go fill in another.
  3480.         jmp cmifi1              ; Get the next char.
  3481. cmifi7: cmp ah,'0'
  3482.         jl cmif8x
  3483.         cmp ah,'z'+1
  3484.         jns cmif8x
  3485.         cmp ah,'A'                      ; Don't capitalize non-alphabetics.
  3486.         jl cmifi8
  3487.         and ah,137O             ; Capitalize.
  3488. cmifi8: mov bx,cmfcb2           ; Get the pointer into the FCB.
  3489.         mov [bx],ah                     ; Put the char there.
  3490.         inc bx
  3491.         mov cmfcb2,bx
  3492.         inc ch
  3493.         jmp cmifi1
  3494.  
  3495. cmif8x: push es
  3496.         mov cx,ds
  3497.         mov es,cx               ; Scan uses ES register.
  3498.         mov di,offset spchar    ; Special chars.
  3499.         mov cx,20               ; Twenty of them.
  3500.         mov al,ah               ; Char is in al.
  3501.         repnz scasb             ; Search string for input char.
  3502.         cmp cx,0                ; Was it there?
  3503.         pop es
  3504.         jnz cmifi8
  3505.  
  3506. cmifi9: mov ah,prstr
  3507.         mov dx,offset cmer02
  3508.         int dos
  3509.         ret
  3510.  
  3511. cmofil: jmp cmifil              ; For now, the same as CMIFI.
  3512.  
  3513.  
  3514.  
  3515. cminbf: push dx
  3516.         push bx
  3517.         mov cx,dx               ; Save value here too.
  3518.         mov ah,cmaflg           ; Is the action char flag set?
  3519.         cmp ah,0
  3520.         je cminb1
  3521.         jmp cminb9              ; If so get no more chars.
  3522. cminb1: inc cmccnt              ; Increment the char count.
  3523.         mov ah,conin            ; Get a char.
  3524.         int dos
  3525.         mov ah,al               ; Keep char in 'ah'.
  3526.         mov bx,cmcptr           ; Get the pointer into the buffer.
  3527.         mov [bx],ah                     ; Put it in the buffer.
  3528.         inc bx
  3529.         mov cmcptr,bx
  3530.         cmp ah,25O                      ; Is it a ^U?
  3531.         jne cminb2
  3532. cmnb12: mov ah,prstr
  3533.         mov dx,offset clrlin
  3534.         int dos
  3535.         mov ax,0920H                    ; Write spaces.
  3536.         mov bx,7                   ; Clear the line.
  3537.         mov cx,80
  3538.         int bios
  3539.         mov ah,prstr
  3540.         mov dx,cmprmp           ; Print the prompt.
  3541.         int dos
  3542.         mov bx,offset cmdbuf
  3543.         mov cmcptr,bx           ; Reset the point to the start.
  3544.         mov cmccnt,0               ; Zero the count.
  3545.         mov dx,cx               ; Preserve original value of dx.
  3546.         jmp repars              ; Go start over.
  3547. cminb2: cmp ah,10O                      ; Or backspace?
  3548.         jz cminb3
  3549.         cmp ah,del                      ; Delete?
  3550.         jne cminb4
  3551.         mov ah,prstr            ; Print the delete string.
  3552.         mov dx,offset delstr
  3553.         int dos
  3554. cminb3: mov ah,cmccnt           ; Decrement the char count by two.
  3555.         dec ah
  3556.         dec ah
  3557.         cmp ah,0                        ; Have we gone too far?
  3558.         jns cmnb32              ; If not proceed.
  3559.         mov ah,conout           ; Ring the bell.
  3560.         mov dl,bell
  3561.         int dos
  3562.         jmp cmnb12              ; Go reprint prompt and reparse.
  3563. cmnb32: mov cmccnt,ah           ; Save the new char count.
  3564.         mov ah,prstr            ; Erase the character.
  3565.         mov dx,offset clrspc
  3566.         int dos
  3567.         mov bx,cmcptr           ; Get the pointer into the buffer.
  3568.         dec bx                  ; Back up in the buffer.
  3569.         dec bx
  3570.         mov cmcptr,bx
  3571.         jmp repars              ; Go reparse everything.
  3572. cminb4: cmp ah,'?'                      ; Is it a question mark.
  3573.         jz cminb6
  3574.         cmp ah,esc                      ; Is it an escape?
  3575.         jz cminb8
  3576.         cmp ah,cr                       ; Is it a carriage return?
  3577.         jz cminb5
  3578.         cmp ah,lf                       ; Is it a line feed?
  3579.         jz cminb5
  3580.         cmp ah,ff                       ; Is it a formfeed?
  3581.         jne cminb7
  3582.         call cmblnk
  3583.         call locate
  3584. cminb5: mov ah,cmccnt           ; Have we parsed any chars yet?
  3585.         cmp ah,1
  3586.         jnz cminb6
  3587.         jmp prserr               ; If not, just start over.
  3588. cminb6: mov ah,0FFH             ; Set the action flag.
  3589.         mov cmaflg,ah
  3590.         jmp cminb9
  3591. cminb7: jmp cminb1              ; Get another char.
  3592.  
  3593. cminb8: mov ah,prstr            ; Don't print the escape char.
  3594.         mov dx,offset escspc
  3595.         int dos
  3596.         jmp cminb6
  3597.  
  3598. cminb9: pop bx
  3599.         pop dx
  3600.         ret
  3601.  
  3602. cmgtch: push cx
  3603.         push bx
  3604.         push dx
  3605. cmgtc1: mov ah,cmaflg
  3606.         cmp ah,0                        ; Is it set.
  3607.         jne cmgt10
  3608.         call cminbf             ; If the action char flag is not set get more.
  3609. cmgt10: mov bx,cmdptr           ; Get a pointer into the buffer.
  3610.         mov ah,[bx]                     ; Get the next char.
  3611.         inc bx
  3612.         mov cmdptr,bx
  3613.         cmp ah,' '                      ; Is it a space?
  3614.         jz cmgtc2
  3615.         cmp ah,tab                      ; Or a tab?
  3616.         jne cmgtc3
  3617. cmgtc2: mov ah,cmsflg           ; Get the space flag.
  3618.         cmp ah,0                        ; Was the last char a space?
  3619.         jne cmgtc1              ; Yes, get another char.
  3620.         mov ah,0FFH             ; Set the space flag.
  3621.         mov cmsflg,ah
  3622.         mov ah,' '
  3623.         pop dx
  3624.         pop bx
  3625.         jmp cmgtc5
  3626. cmgtc3: mov al,0
  3627.         mov cmsflg,al           ; Zero the space flag.
  3628.         pop dx
  3629.         pop bx
  3630.         cmp ah,esc
  3631.         jz cmgtc5
  3632.         cmp ah,'?'                      ; Is the user curious?
  3633.         jz cmgtc4
  3634.         cmp ah,cr
  3635.         jz cmgtc4
  3636.         cmp ah,lf
  3637.         jz cmgtc4
  3638.         cmp ah,ff
  3639.         je cmgtc4
  3640.         pop cx
  3641.         ret                     ; Not an action char, just return.
  3642. cmgtc4: dec cmdptr
  3643. cmgtc5: or ah,80H               ; Make the char negative to indicate
  3644.         pop cx
  3645.         ret                     ; it is a terminator.
  3646. CMND    ENDP
  3647.  
  3648. ; This routine blanks the screen.
  3649.  
  3650. CMBLNK  PROC    NEAR            ; This is stolen from the IBM example.
  3651.         mov cx,0
  3652.         mov dx,184FH
  3653.         mov bh,7
  3654.         mov ax,600H
  3655.         int bios
  3656.         ret
  3657. CMBLNK  ENDP
  3658.  
  3659. ; Cursor control.
  3660.  
  3661. LOCATE  PROC    NEAR
  3662.         mov dx,0                ; Go to top left corner of screen.
  3663.         mov bh,0
  3664.         mov ah,2
  3665.         int bios
  3666.         ret
  3667. LOCATE  ENDP
  3668.  
  3669.  
  3670. MAIN    ENDS                    ; End of code section.
  3671.         END     START
  3672.